
/*/======== CSCI402 Project 2 ========*/

#include "../userprog/syscall.h"

/*/======== Global Data ========*/

void Customer();
void MovieTechnician();
void TicketClerk();
void ConcessionClerk();
void TicketTaker();
void Manager();

int PRINT_DEBUG_MESSAGES = 0;
int PRINT_OUTPUT_MESSAGES = 1;
int PRINT_TEST_CASE_MESSAGES = 0;
int ENABLE_BREAKS = 0;

int latestIndex; /*/used to pass index to newly forked threads*/
int latestIndexLock;
int latestIndexCondition;

/*/-------- Constants --------*/

/*/monetary constants*/
const int TICKET_PRICE = 12;
const int POPCORN_PRICE = 5;
const int SODA_PRICE = 4;

/*/clerk amounts*/
#define NUM_TICKET_CLERKS 5
#define NUM_CONCESSION_CLERKS 5
#define NUM_TICKET_TAKERS 3

/*/customer amounts*/
int NUM_CUSTOMERS = 40;
const int NUM_GROUPS = 20;
const int MAX_GROUP_SIZE = 5;

/*/customer probability constants*/
const int CUSTOMER_WANT_POPCORN_PROBABILITY = 75;
const int CUSTOMER_WANT_SODA_PROBABILITY = 75;
const int CUSTOMER_WANT_BATHROOM_PROBABILITY = 25;

/*/screening room properties*/
#define SCREENING_ROOM_ROWS 5
#define SCREENING_ROOM_COLS 5
#define SCREENING_ROOM_CAPACITY 25

/*/manager probability constants*/
const int MANAGER_DELAY_ACCEPTING = 1; /*/ nonzero: bigger numbers and the manager will roll less often to start movie process*/
const int MANAGER_ROLL_ACCEPT = 50; /*/ % chance to start movie process when deciding to roll for it*/
const int MANAGER_YIELD_ACCEPTING = 15; /*/manager yields cpu this many times after activating ticket takers so he doesnt randomly set state to CUSTOMER_CUTOFF too soon.*/
const int MANAGER_DELAY_CUTOFF = 1; /*/nonzero: bigger numbers and the manager will stop the taking of tickets so the movie will start less often*/
const int MANAGER_DELAY_PROFITS = 5; /*/nonzero: bigger numbers and the manager will check profits less often*/
const int MANAGER_DELAY_BREAK = 1;/*/ nonzero: bigger numbers and the manager will roll to put people on break less often*/
const int MANAGER_ROLL_ONBREAK = 20;/*/% chance to put someone on break when rolling to decide to do it*/

const int MANAGER_LONGLINE = 5; /*/lines longer than this end breaks*/
const int MANAGER_SHORTLINE = 3; /*/lines shorter than this start breaks*/

/*/movie technician*/
/*/const int MOVIETECH_YIELD = 30;*/

/*/-------- Enums --------*/

/*/customer initialization modes*/
const int CONSTANT_NUMBER_OF_CUSTOMERS = 0, CONSTANT_NUMBER_OF_GROUPS = 1;
int CUSTOMER_INIT_MODE;

/*/clerk states*/
const int CLERK_ON_BREAK = -1, CLERK_AVAILABLE = 0, CLERK_BUSY = 1;

/*/movie process states*/
const int ROOM_EMPTY = 0, ACCEPTING_TICKETS = 1, CUSTOMER_CUTOFF = 2, IN_PROGRESS = 3, ROOM_EMPTYING = 4;
int MOVIE_STATE;

/*/-------- General movie theater data --------*/

int numCustomersInTheater;
int numCustomersInTheaterLock;
int numGroupsInTheater;
int numGroupsInTheaterLock;

/*/int* totalTicketsSold;*/
/*/int* totalPopcornSold;*/
/*/int* totalSodaSold;*/

int totalTicketsSold [NUM_TICKET_CLERKS];
int totalPopcornSold [NUM_CONCESSION_CLERKS];
int totalSodaSold [NUM_CONCESSION_CLERKS];

int ticketCountBox;
int ticketCountBoxLock;

int movieStateLock;
int movieNumber;

/*/-------- Special/Testing data --------*/

int overrideExitCondition;
int overrideExitLock;

/*/-------- Screening room data --------*/
int screeningRoomSeat[SCREENING_ROOM_ROWS][SCREENING_ROOM_COLS];
int screeningRoomLock;
int movieInProgressLock;
int movieInProgressCondition;

/*/-------- Data, Locks, and Conditions controlling the Customers --------*/

int customerInitLock;
int customerInitCondition;
int customerStartLock;
int customerStartCondition;

/*/-------- Data, Locks, and Conditions controlling the TicketClerks --------*/

/*/int* tcLineLength;*/
int tcLineLength [NUM_TICKET_CLERKS];
int tcLineManager;
/*/Lock** tcInteractionLock;*/
/*/Condition** tcLineCondition;*/
/*/Condition** tcInteractionCondition;*/
	int tcInteractionLock [NUM_TICKET_CLERKS];
	int tcLineCondition [NUM_TICKET_CLERKS];
	int tcInteractionCondition [NUM_TICKET_CLERKS];

/*/int* tcState;*/
int tcState [NUM_TICKET_CLERKS];
/*/Lock** tcStateLock;*/
int tcStateLock [NUM_TICKET_CLERKS];
/*/Condition** tcStateCondition;*/
int tcStateCondition [NUM_TICKET_CLERKS];



/*/int* numTicketsDesired;*/
int numTicketsDesired [NUM_TICKET_CLERKS];

/*/-------- Data, Locks, and Conditions controlling the ConcessionClerks --------*/

/*/int* ccLineLength;*/
int ccLineLength [NUM_CONCESSION_CLERKS];
int ccLineManager;
/*/Lock** ccInteractionLock;*/
/*/Condition** ccLineCondition;*/
/*/Condition** ccInteractionCondition;*/
int ccInteractionLock [NUM_CONCESSION_CLERKS];
int ccLineCondition [NUM_CONCESSION_CLERKS];
int ccInteractionCondition [NUM_CONCESSION_CLERKS];

int ccState [NUM_CONCESSION_CLERKS];
int ccStateLock [NUM_CONCESSION_CLERKS];
int ccStateCondition [NUM_CONCESSION_CLERKS];

int numPopcornDesired [NUM_CONCESSION_CLERKS];
int numSodaDesired [NUM_CONCESSION_CLERKS];


/*/int* ccState;*/
/*/Lock** ccStateLock;*/
/*/Condition** ccStateCondition;*/

/*/int* numPopcornDesired;*/
/*/int* numSodaDesired;*/

/*/-------- Data, Locks, and Conditions controlling the TicketTakers --------*/

/*/int* ttLineLength;*/
int ttLineManager;
/*/Lock** ttInteractionLock;*/
/*/Condition** ttLineCondition;*/
/*/Condition** ttInteractionCondition;*/
/*/Condition** ttLobbyCondition;*/
/*/Lock** ttLobbyLock;*/

int ticketTakerFullLock;
/*/int* ticketTakerFull;*/
/*/int* ticketTakerSaidToProceed;*/
/*/int* ttState;*/
/*/Lock** ttStateLock;*/
/*/Condition** ttStateCondition;*/

int ttStopLock;
int ttStopCondition;

int ttLineLength [NUM_TICKET_TAKERS];

int ttInteractionLock [NUM_TICKET_TAKERS];
int ttLineCondition [NUM_TICKET_TAKERS];
int ttInteractionCondition [NUM_TICKET_TAKERS];
int ttLobbyLock [NUM_TICKET_TAKERS + 1];
int ttLobbyCondition [NUM_TICKET_TAKERS + 1];


int ticketTakerFull [NUM_TICKET_TAKERS];
int ticketTakerSaidToProceed [NUM_TICKET_TAKERS];
int ttState [NUM_TICKET_TAKERS];
int ttStateLock [NUM_TICKET_TAKERS];
int ttStateCondition [NUM_TICKET_TAKERS];

int numTicketsGiven [NUM_TICKET_TAKERS];

int ttForcedToStop [NUM_TICKET_TAKERS];



/*/int* ttForcedToStop;*/

/*/int* numTicketsGiven;*/

/*/-------- Data, Locks, and Conditions used by the Manager -------*/

/*/Lock** beginTakingTicketsLock;*/
/*/Condition** beginTakingTicketsCondition;*/
int tcsOnBreak;
int ccsOnBreak;
int ttsOnBreak;
/*
//Lock** tcBreakLock;
//Lock** tcBreakStopLock;
//Condition** tcBreakCondition;
//Condition** tcBreakStopCondition;
//Lock** ccBreakLock;
//Lock** ccBreakStopLock;
//Condition** ccBreakCondition;
//Condition** ccBreakStopCondition;
//Lock** ttBreakLock;
//Lock** ttBreakStopLock;
//Condition** ttBreakCondition;
//Condition** ttBreakStopCondition;
*/
int beginTakingTicketsLock [NUM_TICKET_TAKERS];
int beginTakingTicketsCondition [NUM_TICKET_TAKERS];


int tcBreakLock [NUM_TICKET_CLERKS];
int tcBreakCondition [NUM_TICKET_CLERKS];
int tcBreakStopLock [NUM_TICKET_CLERKS];
int tcBreakStopCondition [NUM_TICKET_CLERKS];

int ccBreakLock [NUM_CONCESSION_CLERKS];
int ccBreakCondition [NUM_CONCESSION_CLERKS];
int ccBreakStopLock [NUM_CONCESSION_CLERKS];
int ccBreakStopCondition [NUM_CONCESSION_CLERKS];

int ttBreakLock [NUM_TICKET_TAKERS];
int ttBreakCondition [NUM_TICKET_TAKERS];
int ttBreakStopLock [NUM_TICKET_TAKERS];
int ttBreakStopCondition [NUM_TICKET_TAKERS];



/*/======== Function that returns the number of available seats in the theater ========*/
int getNumAvailableSeats()
{
	int r;
	int total = 0;
	
	for(r = 0; r < SCREENING_ROOM_ROWS; r++)
	{
		total += getNumFreeSeats(r);
	}
	
	return total;
}

/*/======== Function that returns the number of taken seats in the theater ========*/
int getNumTakenSeats()
{
	return SCREENING_ROOM_CAPACITY - getNumAvailableSeats();
}

/*/-------- Data, Locks, and Conditions used by the Manager -------*/

int movieTechLock;
int movieTechCondition;
int profitLock;

/*/======== Function that returns the number of free seats in a screening room row ========*/
int getNumFreeSeats(int row)
{
	int freeSeats = 0;
	int col;
	for(col = 0; col < SCREENING_ROOM_COLS; col++)
	{
		if(screeningRoomSeat[row][col] < 0)
		{
			freeSeats++;
		}
	}
	return freeSeats;
}

/*/======== Function that returns the index of the biggest row ========*/
int getBiggestRow()
{
	int r;
	int biggestRow = 0;
	int biggestRowSize;
	int freeSeats;
	biggestRowSize = getNumFreeSeats(0);
	
	for(r = 1; r < SCREENING_ROOM_ROWS; r++)
	{
		freeSeats = getNumFreeSeats(r);
		
		if(freeSeats > biggestRowSize)
		{
			biggestRow = r;
			biggestRowSize = getNumFreeSeats(r);
		}
	}
	
	return biggestRow;
}

/*/======== Function that returns the index of the smallest row that fits a specified number of people ========*/
int getSmallestRowThatFits(int numPeopleToSeat)
{
	int r;
	int q;
	int rowThatFitsExists = 0;
	int smallestRowThatFits = -1;
	for(r = 0; r < SCREENING_ROOM_ROWS; r++)
	{
		if(getNumFreeSeats(r) >= numPeopleToSeat)
		{
			smallestRowThatFits = r;
			rowThatFitsExists = 1;
			break;
		}
	}
	
	if(smallestRowThatFits == -1)
	{
		return -1;
	}
	else
	{
		int smallestRowThatFitsSize = getNumFreeSeats(smallestRowThatFits);
		for(q = 0; q < SCREENING_ROOM_ROWS; q++)
		{
			int numFreeSeats = getNumFreeSeats(q);
			if(numFreeSeats >= numPeopleToSeat && numFreeSeats < smallestRowThatFitsSize)
			{
				smallestRowThatFits = q;
				smallestRowThatFitsSize = getNumFreeSeats(q);
			}
		}
		
		return smallestRowThatFits;
	}
}

/*/======== Sets up the movie theater ========*/
/*
void setupMovieTheater(int numTicketClerks, int numConcessionClerks, int numTicketTakers,
	int numCustomers, int numGroups, int maxGroupSize, int customerInitMode,
	int printTestCaseMessages, int enableBreaks)
{
	NUM_TICKET_CLERKS = numTicketClerks;
	NUM_CONCESSION_CLERKS = numConcessionClerks;
	NUM_TICKET_TAKERS = numTicketTakers;
	NUM_CUSTOMERS = numCustomers;
	NUM_GROUPS = numGroups;
	MAX_GROUP_SIZE = maxGroupSize;
	
	if(customerInitMode == CONSTANT_NUMBER_OF_CUSTOMERS)
	{
	#define customized 1
	}
	CUSTOMER_INIT_MODE = customerInitMode;
	
	PRINT_TEST_CASE_MESSAGES = printTestCaseMessages;
	
	ENABLE_BREAKS = enableBreaks;
	
	setupMovieTheater();
}
*/
void setupMovieTheater()
{
int i;
int r;
int c;
MOVIE_STATE = ROOM_EMPTY;
CUSTOMER_INIT_MODE = CONSTANT_NUMBER_OF_GROUPS;
latestIndex = 0; /*/used to pass index to newly forked threads*/
latestIndexLock = CreateLock();
latestIndexCondition = CreateCondition();
tcLineManager = CreateLock();

	if(PRINT_DEBUG_MESSAGES) FPrint("Setting up movie theater...\n", 29, 0, 0);
	
	/*/-------- Global data --------*/
	
	numCustomersInTheater = 0;
	numCustomersInTheaterLock = CreateLock();
	numGroupsInTheater = 0;
	numGroupsInTheaterLock = CreateLock();
	/*
	//int totalTicketsSold [NUM_TICKET_CLERKS];
	//int totalPopcornSold [NUM_CONCESSION_CLERKS];
	//int totalSodaSold [NUM_CONCESSION_CLERKS];
*/
	ticketCountBox = 0;
	ticketCountBoxLock = CreateLock();
	
	movieStateLock = CreateLock();
	movieNumber = 0;
	
	/*/-------- Special/Testing data --------*/
	
	overrideExitCondition = CreateCondition();
	overrideExitLock = CreateLock();
	
	/*/-------- Screening room data --------*/
	
	/*/int screeningRoomSeat [SCREENING_ROOM_ROWS] [SCREENING_ROOM_COLS];*/
	for(r = 0; r < SCREENING_ROOM_ROWS; r++)
	{
		/*/screeningRoomSeat[r] = new int[SCREENING_ROOM_COLS];*/
		for(c = 0; c < SCREENING_ROOM_COLS; c++)
		{
			screeningRoomSeat[r][c] = -1;
		}
	}
	
	screeningRoomLock = CreateLock();
	movieInProgressLock = CreateLock();
	movieInProgressCondition = CreateCondition();
	
	/*/-------- Customer data --------*/
	
	customerInitLock = CreateLock();
	customerInitCondition = CreateCondition();
	customerStartLock = CreateLock();
	customerStartCondition = CreateCondition();
	
	/*/-------- TicketClerk data --------*/
	/*
	//int tcLineLength [NUM_TICKET_CLERKS];
	//tcLineManager = CreateLock();
	//int tcInteractionLock [NUM_TICKET_CLERKS];
	//int tcLineCondition [NUM_TICKET_CLERKS];
	//int tcInteractionCondition [NUM_TICKET_CLERKS];
	
	//int tcState [NUM_TICKET_CLERKS];
	//int tcStateLock [NUM_TICKET_CLERKS];
	//int tcStateCondition [NUM_TICKET_CLERKS];
	
	//int numTicketsDesired [NUM_TICKET_CLERKS];
	*/
	/*/-------- ConcessionClerk data --------*/
	
	/*/int ccLineLength [NUM_CONCESSION_CLERKS];*/
	ccLineManager = CreateLock();
	/*
	//int ccInteractionLock [NUM_CONCESSION_CLERKS];
	//int ccLineCondition [NUM_CONCESSION_CLERKS];
	//int ccInteractionCondition [NUM_CONCESSION_CLERKS];
	
	//int ccState [NUM_CONCESSION_CLERKS];
	//int ccStateLock [NUM_CONCESSION_CLERKS];
	//int ccStateCondition [NUM_CONCESSION_CLERKS];
	
	//int numPopcornDesired [NUM_CONCESSION_CLERKS];
	//int numSodaDesired [NUM_CONCESSION_CLERKS];
	*/
	
	/*/-------- TicketTaker data --------*/
	ttLineManager = CreateLock();
	ticketTakerFullLock = CreateLock();
	ttStopCondition = CreateCondition();
	ttStopLock = CreateLock();
	/*
	//int ttLineLength [NUM_TICKET_TAKERS];
	
	//int ttInteractionLock [NUM_TICKET_TAKERS];
	//int ttLineCondition [NUM_TICKET_TAKERS];
	//int ttInteractionCondition [NUM_TICKET_TAKERS];
	//int ttLobbyLock [NUM_TICKET_TAKERS + 1];
	//int ttLobbyCondition [NUM_TICKET_TAKERS + 1];
	
	
	//int ticketTakerFull [NUM_TICKET_TAKERS];
	//int ticketTakerSaidToProceed [NUM_TICKET_TAKERS];
	//int ttState [NUM_TICKET_TAKERS];
	//int ttStateLock [NUM_TICKET_TAKERS];
	//int ttStateCondition [NUM_TICKET_TAKERS];
	
	//int numTicketsGiven [NUM_TICKET_TAKERS];
	
	//int ttForcedToStop [NUM_TICKET_TAKERS];
	*/
	
	
	/*/-------- Manager data --------*/
	
	profitLock = CreateLock();
	tcsOnBreak = 0;
	ccsOnBreak = 0;
	ttsOnBreak = 0;
	/*
	//int beginTakingTicketsLock [NUM_TICKET_TAKERS];
	//int beginTakingTicketsCondition [NUM_TICKET_TAKERS];
	
	
	//int tcBreakLock [NUM_TICKET_CLERKS];
	//int tcBreakCondition [NUM_TICKET_CLERKS];
	//int tcBreakStopLock [NUM_TICKET_CLERKS];
	//int tcBreakStopCondition [NUM_TICKET_CLERKS];
	
	//int ccBreakLock [NUM_CONCESSION_CLERKS];
	//int ccBreakCondition [NUM_CONCESSION_CLERKS];
	//int ccBreakStopLock [NUM_CONCESSION_CLERKS];
	//int ccBreakStopCondition [NUM_CONCESSION_CLERKS];
	
	//int ttBreakLock [NUM_TICKET_TAKERS];
	//int ttBreakCondition [NUM_TICKET_TAKERS];
	//int ttBreakStopLock [NUM_TICKET_TAKERS];
	//int ttBreakStopCondition [NUM_TICKET_TAKERS];
	*/
	
	
	/*/-------- MovieTech data --------*/
	
	movieTechLock = CreateLock();
	movieTechCondition = CreateCondition();
	
	/*/======== Array Initialization ========*/
	
	for(i = 0; i < NUM_TICKET_CLERKS; i++)
	{
		/*/-------- TicketClerk data --------*/
		
		totalTicketsSold[i] = 0;
		
		tcLineLength[i] = 0;
		tcInteractionLock[i] = CreateLock();
		tcLineCondition[i] = CreateCondition();
		tcInteractionCondition[i] = CreateCondition();
		
		tcState[i] = CLERK_AVAILABLE;
		tcStateLock[i] = CreateLock();
		tcStateCondition[i] = CreateCondition();
		
		numTicketsDesired[i] = 0;
		
		tcBreakLock[i] = CreateLock();
		tcBreakCondition[i] = CreateCondition();
		tcBreakStopLock[i] = CreateLock();
		tcBreakStopCondition[i] = CreateCondition();
	}
	
	for(i = 0; i < NUM_CONCESSION_CLERKS; i++)
	{
		/*/-------- ConcessionClerk data --------*/
		
		totalPopcornSold[i] = 0;
		totalSodaSold[i] = 0;
		
		ccLineLength[i] = 0;
		ccInteractionLock[i] = CreateLock();
		ccLineCondition[i] = CreateCondition();
		ccInteractionCondition[i] = CreateCondition();
		
		ccState[i] = CLERK_AVAILABLE;
		ccStateLock[i] = CreateLock();
		ccStateCondition[i] = CreateCondition();
		
		numPopcornDesired[i] = 0;
		numSodaDesired[i] = 0;
		
		ccBreakLock[i] = CreateLock();
		ccBreakCondition[i] = CreateCondition();
		ccBreakStopLock[i] = CreateLock();
		ccBreakStopCondition[i] = CreateCondition();
	}
	
	/*/-------- TicketTakers data --------*/
	
	for(i = 0; i < NUM_TICKET_TAKERS; i++)
	{
		
		ttLineLength[i] = 0;
		ttInteractionLock[i] = CreateLock();
		ttLineCondition[i] = CreateCondition();
		ttInteractionCondition[i] = CreateCondition();
		
		ticketTakerFull[i] = 1;
		ticketTakerSaidToProceed[i] = 0;
		ttState[i] = CLERK_AVAILABLE;
		
		numTicketsGiven[i] = 0;
		
		ttForcedToStop[i] = 0;
		
		ttStateLock[i] = CreateLock();
		ttStateCondition[i] = CreateCondition();
		
		ttBreakLock[i] = CreateLock();
		ttBreakCondition[i] = CreateCondition();
		ttBreakStopLock[i] = CreateLock();
		ttBreakStopCondition[i] = CreateCondition();
		
	}
	for(i = 0; i < NUM_TICKET_TAKERS + 1; i++)
	{
		ttLobbyLock[i] = CreateLock();
		ttLobbyCondition[i] = CreateCondition();
	}
	
	/*/-------- Manager data --------*/
	
	for(i = 0; i < NUM_TICKET_TAKERS; i++)
	{
		beginTakingTicketsLock[i] = CreateLock();
		beginTakingTicketsCondition[i] = CreateCondition();
	}
	
	/*/======== Main Initialization Thread ========*/
	
	if(PRINT_DEBUG_MESSAGES) FPrint("Setup complete, starting threads...\n", 37, 0, 0);
	
	/*/Thread* t;*/
	
	/*/initialize Customers*/
	if(PRINT_DEBUG_MESSAGES) FPrint("Initializing customers\n", 24, 0, 0);
	
	if(CUSTOMER_INIT_MODE == CONSTANT_NUMBER_OF_GROUPS)
	{
		for(latestIndex = 0; latestIndex < NUM_GROUPS; latestIndex++)
		{
			AcquireLock(customerInitLock);
			
			Fork(Customer);
			/*/i++;*/
			
			/*/Allow the newly forked customer to initialize*/
			WaitCondition(customerInitCondition, customerInitLock);
			AcquireLock(customerStartLock);
			ReleaseLock(customerStartLock);
			ReleaseLock(customerInitLock);
		}
		
		NUM_CUSTOMERS = numCustomersInTheater;
	}
	
	
	/* REMOVED CUSTOM THEATER
	else if(CUSTOMER_INIT_MODE == CONSTANT_NUMBER_OF_CUSTOMERS)
	{
		latestIndex = 0;
		while(numCustomersInTheater < NUM_CUSTOMERS)
		{
			AcquireLock(customerInitLock);
			
			Fork(Customer);
			
			
			/*Allow the newly forked customer to initialize*
			WaitCondition(customerInitCondition, customerInitLock);
			AcquireLock(customerStartLock);
			ReleaseLock(customerStartLock);
			ReleaseLock(customerInitLock);
			
			latestIndex++;
		}
		
		NUM_GROUPS = numGroupsInTheater;
	}
	*/
	
	
	/*/======== Preliminary Print Outputs ========*/
	
	if(PRINT_OUTPUT_MESSAGES)
	{
		FPrint("\n", 2, 0, 0);
		FPrint("===========================================\n", 45, 0, 0);
		FPrint("\n", 2, 0, 0);
		FPrint("Initializing movie theater...done\n", 35, 0, 0);
		FPrint("\n", 2, 0, 0);
		FPrint("Number of Customers = %d\n", 26, 1, NUM_CUSTOMERS);
		FPrint("Number of Groups = %d\n", 23, 1, NUM_GROUPS);
		FPrint("Number of TicketClerks = %d\n", 29, 1, NUM_TICKET_CLERKS);
		FPrint("Number of ConcessionClerks = %d\n", 33, 1, NUM_CONCESSION_CLERKS);
		FPrint("Number of TicketTakers = %d\n", 29, 1, NUM_TICKET_TAKERS);
		FPrint("\n", 2, 0, 0);
		FPrint("===========================================\n", 45, 0, 0);
		FPrint("\n", 2, 0, 0);
	}
	
	if(PRINT_DEBUG_MESSAGES)
	{
		FPrint("\n", 2, 0, 0);
		FPrint("===========================================\n", 45, 0, 0);
		FPrint("\n", 2, 0, 0);
		FPrint("Initializing movie theater...done\n", 35, 0, 0);
		FPrint("\n", 2, 0, 0);
		FPrint("Number of Customers = %d\n", 26, 1, NUM_CUSTOMERS);
		FPrint("Number of Groups = %d\n", 23, 1, NUM_GROUPS);
		FPrint("Number of TicketClerks = %d\n", 29, 1, NUM_TICKET_CLERKS);
		FPrint("Number of ConcessionClerks = %d\n", 33, 1, NUM_CONCESSION_CLERKS);
		FPrint("Number of TicketTakers = %d\n", 29, 1, NUM_TICKET_TAKERS);
		FPrint("\n", 2, 0, 0);
		FPrint("===========================================\n", 45, 0, 0);
		FPrint("\n", 2, 0, 0);
	}
	
	/*/initialize MovieTech*/
	Fork(MovieTechnician); /*/theres only one so this is hardcoded to be zero*/
	
	/*/initialize TicketClerks*/

	for(latestIndex = 0; latestIndex < NUM_TICKET_CLERKS; latestIndex++)
	{
		AcquireLock(latestIndexLock);
		
		Fork(TicketClerk);
		
		/*//Allow the newly forked ticketclerk to initialize*/
		WaitCondition(latestIndexCondition, latestIndexLock);
		ReleaseLock(latestIndexLock);
	}

	/*//initialize ConcessionClerks*/

	for(latestIndex = 0; latestIndex < NUM_CONCESSION_CLERKS; latestIndex++)
	{
		AcquireLock(latestIndexLock);
		Fork(ConcessionClerk);
		
		/*//Allow the newly forked ticketclerk to initialize/*/
		WaitCondition(latestIndexCondition, latestIndexLock);
		ReleaseLock(latestIndexLock);
	}

	/*//initialize TicketTakers/*/
	for(latestIndex = 0; latestIndex < NUM_TICKET_TAKERS; latestIndex++)
	{
		AcquireLock(latestIndexLock);
		
		Fork(TicketTaker);
		/*//Allow the newly forked ticketclerk to initialize/*/
		WaitCondition(latestIndexCondition, latestIndexLock);
		ReleaseLock(latestIndexLock);
	}
	
	
	
	/*//initialize Manager/*/
	if(PRINT_DEBUG_MESSAGES) FPrint("Initializing manager\n", 22, 0, 0);
	Fork(Manager);
	
	/*//start all customers/*/
	if(PRINT_DEBUG_MESSAGES) FPrint("Broadcasting to start %d customers\n", 36, 1, numCustomersInTheater);
	AcquireLock(customerStartLock);
	BroadcastCondition(customerStartCondition, customerStartLock);
	ReleaseLock(customerStartLock);
}
	
/*/======== Customer Function ========*/
void Customer()
{
	int myIndex;
	int customerIndex;
	int needSeats;
	int smallestRowThatFits;
	int biggestRow;
	int biggestRowSize;
	int fillCol;
	int leavingSeatIndex;
	
	int myGroupSize;
	
	int myTicketClerk;
	int myConcessionClerk;
	int myTicketTaker;
	
	int shortestTCLineLength;
	int shortestCCLineLength;
	int shortestTTLineLength;
	
	int numPopcornToOrder;
	int numSodaToOrder;
	
	int proceedToScreeningRoom;
	
	int myLobby;
	
	int bathroomWanted;
	int roll1;
	
	/*Counters*/
	int i1;
	int i2;
	int i3;
	int i4;
	int i5;
	int i6;
	int i7;
	int i8;
	int i9;
	
	
	int c1;
	int r1;
	
	
	myIndex = latestIndex;
	
	/*/Create a random sized group of followers*/
	myGroupSize = RandInt() % MAX_GROUP_SIZE + 1;
	
	/*/Synchronization so number of customers in theater is maintained*/
	AcquireLock(numCustomersInTheaterLock);
	numCustomersInTheater += myGroupSize;
	while(numCustomersInTheater > NUM_CUSTOMERS && CUSTOMER_INIT_MODE == CONSTANT_NUMBER_OF_CUSTOMERS)
	{
		myGroupSize--;
		numCustomersInTheater--;
	}
	ReleaseLock(numCustomersInTheaterLock);
	AcquireLock(numGroupsInTheaterLock);
	numGroupsInTheater++;
	ReleaseLock(numGroupsInTheaterLock);
	
	/*/Only one customer can be initialized at a time*/
	AcquireLock(customerInitLock);
	AcquireLock(customerStartLock);
	/*
	int myTicketClerk;
	int myConcessionClerk;
	int myTicketTaker;
	*/
	SignalCondition(customerInitCondition, customerInitLock);
	ReleaseLock(customerInitLock);
	WaitCondition(customerStartCondition, customerStartLock);
	
	ReleaseLock(customerStartLock);
	
	if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: entered the theater with group size of %d\n", 56, 2, myIndex*100 + myGroupSize);
	for(i1 = 0; i1 < myGroupSize; i1++)
	{
		if(PRINT_OUTPUT_MESSAGES) FPrint("Customer %d in Group %d has entered the movie theater.\n", 56, 2, i1*100 + myIndex);
		Yield();
	}
	
	/*/================ Go To Ticket Clerk ================*/
	
	/*/special case for testing*/
	if(NUM_TICKET_CLERKS == 0)
	{
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: ERROR: No TicketClerks in theater!\n", 49, 1, myIndex);
		if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d: No ConcessionClerks found, leaving theater...\n", 57, 1, myIndex);
		
		AcquireLock(numCustomersInTheaterLock);
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: Decrementing numCustomersInTheater\n", 49, 1, myIndex);
		numCustomersInTheater -= myGroupSize;
		ReleaseLock(numCustomersInTheaterLock);
		
		AcquireLock(numGroupsInTheaterLock);
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: Decrementing numGroupsInTheater\n", 46, 1, myIndex);
		numGroupsInTheater--;
		ReleaseLock(numGroupsInTheaterLock);
		
		AcquireLock(overrideExitLock);
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: leaving theater...\n", 33, 1, myIndex);
		WaitCondition(overrideExitCondition, overrideExitLock);
	}
	
	do
	{
		/*/Begin search for ticket clerks*/
		myTicketClerk = -1;
		
		/*/Lock down all lines from other customers/clerks for search*/
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: acquiring Lock for TicketClerk search\n", 52, 1, myIndex);
		AcquireLock(tcLineManager);

		/*/See if any TicketClerk line is empty*/
		for(i2 = 0;i2 < NUM_TICKET_CLERKS;i2++)
		{
			if(tcState[i2]== CLERK_AVAILABLE)
			{
				if(PRINT_TEST_CASE_MESSAGES)
					FPrint("TicketClerk %d has no line\n",28, 1, i2);
				/*/Join an empty line*/
				myTicketClerk = i2;
				tcState[myTicketClerk] = CLERK_BUSY;
				if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: found available TicketClerk %d\n", 45, 2, myIndex*100 + myTicketClerk);
				
				break;
			}
			else if(tcState[i2] == CLERK_ON_BREAK)
			{
				if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d sees TicketClerk %d is on break\n", 42, 2, myIndex*100 + i2);
			}
		}

		/*/If no lines were empty, join shortest line*/
		if(myTicketClerk  == -1){
			shortestTCLineLength = tcLineLength[0];
			
			
			for(i3 = 0;i3 < NUM_TICKET_CLERKS;i3++)
			{
				if(PRINT_TEST_CASE_MESSAGES)
					FPrint("TicketClerk %d's line length is %d\n", 36, 2, i3*100 + tcLineLength[i3]);
					
				if(tcState[i3] == CLERK_BUSY && shortestTCLineLength >= tcLineLength[i3])
				{
					myTicketClerk = i3;
					shortestTCLineLength = tcLineLength[i3];
				}
				else if(tcState[i3] == CLERK_ON_BREAK)
				{
					if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d sees TicketClerk %d is on break\n", 42, 2, myIndex*100 + i3);
				}
			}
			
			if(myTicketClerk == -1)
			{
				/*/If all ticket clerks are on break, wait in lobby*/
				ReleaseLock(tcLineManager);
				if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: ERROR: all TicketClerks on break\n", 47, 1, myIndex);
				if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d: No TicketClerks found, leaving theater...\n", 53, 1, myIndex);
							
				AcquireLock(numCustomersInTheaterLock);
				if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: Decrementing numCustomersInTheater\n", 49, 1, myIndex);
				numCustomersInTheater -= myGroupSize;
				ReleaseLock(numCustomersInTheaterLock);
				
				AcquireLock(numGroupsInTheaterLock);
				if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: Decrementing numGroupsInTheater\n", 46, 1, myIndex);
				numGroupsInTheater--;
				ReleaseLock(numGroupsInTheaterLock);
				
				AcquireLock(overrideExitLock);
				if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: leaving theater...\n", 33, 1, myIndex);
				WaitCondition(overrideExitCondition, overrideExitLock);
			}
			else
			{
				/*/Get in that line*/
				tcLineLength[myTicketClerk]++;
				
				/*/Wait to be signalled for ticket order*/
				if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: getting in line for TicketClerk %d\n", 49, 2, myIndex*100 + myTicketClerk);
				WaitCondition(tcLineCondition[myTicketClerk], tcLineManager);
			}
		}
	}
	while(myTicketClerk < 0 || tcState[myTicketClerk] == CLERK_ON_BREAK);
	
	/*/Release and allow other customers to search lines*/
	if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: releasing Lock for TicketClerk search\n", 52, 1, myIndex);
	ReleaseLock(tcLineManager);
		
	/*/After being signalled by TicketClerk to interact, lock down current clerk*/
	if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: TicketClerk %d is ready for interaction\n", 54, 2, myIndex*100 + myTicketClerk);
	if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d is walking up to TicketClerk %d to buy %d tickets.\n", 61, 3, myIndex*10000 + myTicketClerk*100 + myGroupSize);
	AcquireLock(tcInteractionLock[myTicketClerk]);

	/*/Give ticket order to clerk and signal TicketClerk to wake up*/
	if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: signalling TicketClerk %d for %d tickets\n", 55, 3,  myIndex*10000 + myTicketClerk*100 + myGroupSize);
	if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d in TicketClerk line %d is paying %d for tickets.\n", 59, 3, myIndex*10000 + myTicketClerk*100 + myGroupSize * TICKET_PRICE);
	
	numTicketsDesired[myTicketClerk] = myGroupSize;
	
	if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: waiting for response\n", 35, 1, myIndex);
	SignalCondition(tcInteractionCondition[myTicketClerk], tcInteractionLock[myTicketClerk]);

	/*/Wait for TicketClerk to give tickets*/
	WaitCondition(tcInteractionCondition[myTicketClerk], tcInteractionLock[myTicketClerk]);
	
	/*/After getting signalled by TicketClerk with completed ticket order*/
	AcquireLock(tcInteractionLock[myTicketClerk]);
	if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: received %d tickets from TicketClerk %d\n", 54, 3, myIndex*1000 + numTicketsDesired[myTicketClerk]*100 + myTicketClerk);
	if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d is leaving TicketClerk %d\n", 36, 2, myIndex*100 + myTicketClerk);
	SignalCondition(tcInteractionCondition[myTicketClerk], tcInteractionLock[myTicketClerk]);
	ReleaseLock(tcInteractionLock[myTicketClerk]);
	
	/*/================ Go To Concession Clerk ================*/
	
	/*/special case for testing*/
	if(NUM_CONCESSION_CLERKS == 0)
	{
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: ERROR: No ConcessionClerks in theater!\n", 53, 1, myIndex);
		if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d: No ConcessionClerks found, leaving theater...\n", 57, 1, myIndex);
		
		AcquireLock(numCustomersInTheaterLock);
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: Decrementing numCustomersInTheater\n", 49, 1, myIndex);
		numCustomersInTheater -= myGroupSize;
		ReleaseLock(numCustomersInTheaterLock);
		
		AcquireLock(numGroupsInTheaterLock);
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: Decrementing numGroupsInTheater\n", 46, 1, myIndex);
		numGroupsInTheater--;
		ReleaseLock(numGroupsInTheaterLock);
		
		AcquireLock(overrideExitLock);
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: leaving theater...\n", 33, 1, myIndex);
		WaitCondition(overrideExitCondition, overrideExitLock);
	}
	
	/*/Calculate amount of popcorn and soda to order*/
	numPopcornToOrder = 0;
	numSodaToOrder = 0;
	
	for(i4 = 0; i4 < myGroupSize; i4++)
	{
		/*/Randomly select popcorn and soda*/
		int popcornWanted = 0;
		int sodaWanted = 0;
		int roll = RandInt() % 100 + 1;
		
		if(roll <= CUSTOMER_WANT_POPCORN_PROBABILITY)
		{
			popcornWanted = 1;
			numPopcornToOrder += popcornWanted;
		}
		
		roll = RandInt() % 100 + 1;
		if(roll <= CUSTOMER_WANT_SODA_PROBABILITY)
		{
			sodaWanted = 1;
			numSodaToOrder += sodaWanted;
		}
		
		Yield();
		
		if(PRINT_OUTPUT_MESSAGES) FPrint("Customer %d in group %d wants %d popcorn and %d soda.\n", 55, 4,
			i4*1000000 + myIndex*10000 + popcornWanted*100 + sodaWanted);
	}
	
	/*/If any food is desired, approach ConcessionClerk lines*/
	if(numPopcornToOrder + numSodaToOrder > 0)
	{
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: %d popcorn and %d soda desired\n", 45, 3, myIndex*10000+ numPopcornToOrder*100 + numSodaToOrder);
		
		do
		{
			/*/Begin search for ConcessionClerk*/
			myConcessionClerk = -1;
			
			/*/Lock down all lines from other customers/clerks for search*/
			if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: acquiring Lock for ConcessionClerk search\n", 56, 1, myIndex);
			AcquireLock(ccLineManager);

			/*/See if any ConcessionClerk line is empty*/
			for(i5 = 0;i5 < NUM_CONCESSION_CLERKS;i5++)
			{
				if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: ConcessionClerk %d is in state: %d\n", 49, 3, myIndex*10000 + i5*100 + ccState[i5]);
				
				if(ccState[i5]== CLERK_AVAILABLE)
				{
					/*/Join an empty line*/
					myConcessionClerk = i5;
					ccState[myConcessionClerk] = CLERK_BUSY;
					if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: found available ConcessionClerk %d\n", 49, 2, myIndex*100 + myConcessionClerk);
					
					break;
				}
				else if(tcState[i5] == CLERK_ON_BREAK)
				{
					if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d sees ConcessionClerk %d is on break\n", 46, 2, myIndex*100 + i5);
				}
			}

			/*/If no lines were empty, join shortest line*/
			if(myConcessionClerk  == -1){
				shortestCCLineLength = ccLineLength[0];
				
				for(i6 = 0;i6 < NUM_CONCESSION_CLERKS;i6++)
				{
					if(ccState[i6] == CLERK_BUSY && shortestCCLineLength >= ccLineLength[i6])
					{
						myConcessionClerk = i6;
						shortestCCLineLength = ccLineLength[i6];
					}
					else if(tcState[i6] == CLERK_ON_BREAK)
					{
						if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d sees ConcessionClerk %d is on break\n", 46, 2, myIndex*100 + i6);
					}
				}
				
				if(myConcessionClerk == -1)
				{					
					/*/If all ConcessionClerks are on break, wait in lobby*/
					ReleaseLock(ccLineManager);
					if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: ERROR: all ConcessionClerks on break!\n", 52, 1, myIndex);
					if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d: No ConcessionClerks found, leaving theater...\n", 57, 1, myIndex);
					
					AcquireLock(numCustomersInTheaterLock);
					if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: Decrementing numCustomersInTheater\n", 49, 1, myIndex);
					numCustomersInTheater -= myGroupSize;
					ReleaseLock(numCustomersInTheaterLock);
					
					AcquireLock(numGroupsInTheaterLock);
					if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: Decrementing numGroupsInTheater\n", 46, 1, myIndex);
					numGroupsInTheater--;
					ReleaseLock(numGroupsInTheaterLock);
					
					AcquireLock(overrideExitLock);
					if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: leaving theater...\n", 33, 1, myIndex);
					WaitCondition(overrideExitCondition, overrideExitLock);
				}
				else
				{
					/*/Get in that line*/
					ccLineLength[myConcessionClerk]++;
					
					/*/Wait to be signalled for food order*/
					if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: getting in line for ConcessionClerk %d\n", 53, 2, myIndex*100 + myConcessionClerk);
					WaitCondition(ccLineCondition[myConcessionClerk], ccLineManager);
				}
			}
		}
		while(myConcessionClerk < 0 || ccState[myConcessionClerk] == CLERK_ON_BREAK);
		
		/*/Release and allow other customers to search lines*/
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: releasing Lock for ConcessionClerk search\n", 56, 1, myIndex);
		ReleaseLock(ccLineManager);
			
		/*/After being signalled by ConcessionClerk to interact, lock down current clerk*/
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: ConcessionClerk %d is ready for interaction\n", 58, 2, myIndex*100 + myConcessionClerk);
		if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d is walking up to ConcessionClerk %d to buy %d popcorn and %d soda.\n", 77, 4,
			myIndex*1000000 + myConcessionClerk*10000 + numPopcornToOrder*100 + numSodaToOrder);
		AcquireLock(ccInteractionLock[myConcessionClerk]);

		/*/Give food order to clerk and signal ConcessionClerk to wake up*/
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: signalling ConcessionClerk %d for %d popcorn and %d soda\n", 71, 4,
			myIndex*1000000 + myConcessionClerk*10000 + numPopcornToOrder*100 + numSodaToOrder);
		if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d in ConcessionClerk line %d is paying %d for food.\n", 60, 3,
			myIndex*10000 + myConcessionClerk*100 + numPopcornToOrder * POPCORN_PRICE + numSodaToOrder * SODA_PRICE);
		
		numPopcornDesired[myConcessionClerk] = numPopcornToOrder;
		numSodaDesired[myConcessionClerk] = numSodaToOrder;
		
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: waiting for response\n", 35, 1, myIndex);
		SignalCondition(ccInteractionCondition[myConcessionClerk], ccInteractionLock[myConcessionClerk]);

		/*/Wait for ConcessionClerk to give food*/
		WaitCondition(ccInteractionCondition[myConcessionClerk], ccInteractionLock[myConcessionClerk]);
		
		/*/After getting signalled by ConcessionClerk with completed ticket order*/
		AcquireLock(ccInteractionLock[myConcessionClerk]);
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: received %d popcorn and %d soda from ConcessionClerk %d\n", 70, 4,
			myIndex*1000000 + numPopcornDesired[myConcessionClerk]*10000 + numSodaDesired[myConcessionClerk]*100 + myConcessionClerk);
		if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d is leaving ConcessionClerk %d\n", 40, 2, myIndex*100 + myConcessionClerk);
		
		SignalCondition(ccInteractionCondition[myConcessionClerk], ccInteractionLock[myConcessionClerk]);
		ReleaseLock(ccInteractionLock[myConcessionClerk]);
	}
	else
	{
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: no food desired, skipping ConcessionClerks\n", 57, 1, myIndex);
	}
	
	/*/=============== Go To TicketTaker ================*/
	
	/*/Flag controlling whether the TicketTaker has allowed the Customer in*/
	proceedToScreeningRoom = 0;
	
	do
	{
		do
		{
			/*/Begin search for TicketTakers*/
			myTicketTaker = -1;
			
			/*/Lock down all lines from other customers/clerks for search*/
			if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: acquiring ttLineManager\n", 38, 1, myIndex);
			AcquireLock(ttLineManager);

			/*/See if any TicketTaker line is empty*/
			for(i7 = 0;i7 < NUM_TICKET_TAKERS;i7++)
			{
				if(ttState[i7]== CLERK_AVAILABLE && !ticketTakerFull[i7] && !ttForcedToStop[i7])
				{
					/*/Join an empty line*/
					myTicketTaker = i7;
					ttState[myTicketTaker] = CLERK_BUSY;
					if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: found available TicketTaker %d\n", 45, 2, myIndex*100 + myTicketTaker);
					
					break;
				}
				else if(tcState[i7] == CLERK_ON_BREAK)
				{
					if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d sees TicketTaker %d is on break\n", 42, 2, myIndex*100 + i7);
				}
			}

			/*/If no lines were empty, join shortest line*/
			if(myTicketTaker  == -1)
			{
				shortestTTLineLength = ttLineLength[0];
				
				for(i8 = 0;i8 < NUM_TICKET_TAKERS;i8++)
				{
					if(ttState[i8] == CLERK_BUSY && shortestTTLineLength >= ttLineLength[i8] && !ticketTakerFull[i8] && !ttForcedToStop[i8])
					{
						myTicketTaker = i8;
						shortestTTLineLength = ttLineLength[i8];
					}
					else if(tcState[i8] == CLERK_ON_BREAK)
					{
						if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d sees TicketTaker %d is on break\n", 42, 2, myIndex*100 + i8);
					}
				}
				
				if(myTicketTaker == -1)
				{
					ReleaseLock(ttLineManager);
					
					/*/If all TicketTakers are on break, wait in lobby*/
					myLobby = NUM_TICKET_TAKERS;					
					if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: all TicketTakers full or on break, going to lobby %d\n", 67, 2, myIndex*100 + myLobby);
					
					if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: acquiring ttLobbyLock %d\n", 39, 2, myIndex*100 + myLobby);
					AcquireLock(ttLobbyLock[myLobby]);
					if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d is in the lobby\n", 26, 1, myIndex);
					WaitCondition(ttLobbyCondition[myLobby], ttLobbyLock[myLobby]);
					
					if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: signalled out of lobby, releasing ttLobbyLock %d\n", 63, 2, myIndex*100 + myLobby);
					if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d is leaving the the lobby\n", 35, 1, myIndex);
					ReleaseLock(ttLobbyLock[myLobby]);
				}
				else
				{
					/*/Get in that line*/
					ttLineLength[myTicketTaker]++;
					
					/*/Wait to be signalled for ticket order*/
					if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: getting in line for TicketTaker %d\n", 49, 2, myIndex*100 + myTicketTaker);
					
					WaitCondition(ttLineCondition[myTicketTaker], ttLineManager);
				}
			} 
			/*/Release and allow other customers to search lines*/
			if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: releasing ttLineManager\n", 38, 1, myIndex);
			ReleaseLock(ttLineManager);
		}
		while(myTicketTaker < 0 || ttState[myTicketTaker] == CLERK_ON_BREAK || ticketTakerFull[myTicketTaker] || ttForcedToStop[myTicketTaker]);
		
		
			
		/*/After being signalled by TicketTaker to interact, lock down current clerk*/
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: TicketTaker %d is ready for interaction. Acquiring ttInteractionLock[%d]\n", 87, 3, myIndex*10000 + myTicketTaker*100 + myTicketTaker);
		if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d is walking up to TicketTaker %d to give %d tickets.\n", 62, 3, myIndex*10000 + myTicketTaker*100 + myGroupSize);
		AcquireLock(ttInteractionLock[myTicketTaker]);

		/*/Give ticket order to clerk and signal TicketTaker to wake up*/
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: signalling TicketTaker %d with %d tickets\n", 56, 3, myIndex*10000 + myTicketTaker*100 + myGroupSize);
		
		numTicketsGiven[myTicketTaker] = myGroupSize;
		SignalCondition(ttInteractionCondition[myTicketTaker], ttInteractionLock[myTicketTaker]);

		/*/Wait for TicketTaker to accept tickets or send to lobby*/
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: acquiring ttLobbyLock %d\n", 39, 2, myIndex*100 + myTicketTaker);
		AcquireLock(ttLobbyLock[myTicketTaker]);
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: waiting for response on ttInteractionLock%d\n", 58, 2, myIndex*100 + myTicketTaker);
		WaitCondition(ttInteractionCondition[myTicketTaker], ttInteractionLock[myTicketTaker]);
		
		/*/After getting signalled by TicketTaker to go to the screening room or lobby	*/
		if(ticketTakerSaidToProceed[myTicketTaker])
		{
			if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: gave %d tickets to TicketTaker %d\n", 48, 3, myIndex*10000 + numTicketsGiven[myTicketTaker]*100 + myTicketTaker);
			if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d is leaving TicketTaker %d\n", 36, 2, myIndex*100 + myTicketTaker);
			proceedToScreeningRoom = 1;
			ReleaseLock(ttLobbyLock[myTicketTaker]);
		}
		else
		{
			ReleaseLock(ttInteractionLock[myTicketTaker]);
			if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: TicketTaker %d full, waiting on ttLobbyLock %d\n", 61, 3, myIndex*10000 + myTicketTaker*100 + myTicketTaker);
			if(PRINT_OUTPUT_MESSAGES) FPrint("Group %d sees TicketTaker %d is no longer taking tickets.  Going to lobby.\n", 76, 2, myIndex*100 + myTicketTaker);
			WaitCondition(ttLobbyCondition[myTicketTaker], ttLobbyLock[myTicketTaker]);
			if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: Signalled out of lobby, releasing ttLobbyLock %d\n", 63, 2, myIndex*100 + myTicketTaker);
			ReleaseLock(ttLobbyLock[myTicketTaker]);
		}
	}
	while(!proceedToScreeningRoom);
	
	if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: proceeding to screening room\n", 43, 1, myIndex);
	SignalCondition(ttInteractionCondition[myTicketTaker], ttInteractionLock[myTicketTaker]);
	if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: Releasing ttInteractionLock[%d]\n", 46, 2, myIndex*100 + myTicketTaker);
	ReleaseLock(ttInteractionLock[myTicketTaker]);
	
	/*/================ Go To Screening Room ================*/
	
	AcquireLock(screeningRoomLock);
	if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: figuring out screening room seating\n", 50, 1, myIndex);
	
	/*/Figure out how to seat followers*/
	customerIndex = 0;
	needSeats = myGroupSize;
	
	while(needSeats > 0)
	{
		if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: Needs %d more seats\n", 34, 2, myIndex*100 + needSeats);
	
		/*/Try to find the smallest row that fits all group members*/
		smallestRowThatFits = getSmallestRowThatFits(needSeats);
		
		if(smallestRowThatFits >= 0)
		{
			if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: Smallest row that fits: %d with %d free seats\n", 60, 3,
				myIndex*10000 + smallestRowThatFits*100 + getNumFreeSeats(smallestRowThatFits));
		}
		else
		{
			if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: No rows fit %d people, proceeding to split group\n", 63, 2,
				myIndex*100 + needSeats);
		}
		
		/*/No row that fits all group members found, */
		if(smallestRowThatFits == -1)
		{
			/*/Find biggest row	*/		
			biggestRow = getBiggestRow();
			biggestRowSize = getNumFreeSeats(biggestRow);
			
			fillCol = 0;
			while(fillCol < SCREENING_ROOM_COLS)
			{
				if(screeningRoomSeat[biggestRow][fillCol] < 0)
				{				
					/*/Fill the seat*/
					screeningRoomSeat[biggestRow][fillCol] = myIndex;
					
					if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d in Group %d has found the following seat: row %d and seat %d\n", 74, 4,
						customerIndex*1000000 + myIndex*10000 + biggestRow*100 + fillCol);
					if(PRINT_OUTPUT_MESSAGES) FPrint("Customer %d in group %d is sitting in a theater room seat.\n", 60, 2,
						customerIndex*100 + myIndex);
					
					/*/Decrement remaining seats, increment current customer*/
					needSeats--;
					customerIndex++;
				}
				
				fillCol++;
			}
			
			/*/Repeat loop with remaining people*/
		}
		else
		{
			/*/Smallest row that fits found, fill row and fill members in*/
			fillCol = 0;
			while(needSeats > 0)
			{	
				if(screeningRoomSeat[smallestRowThatFits][fillCol] < 0)
				{
					/*/Fill the seat*/
					screeningRoomSeat[smallestRowThatFits][fillCol] = myIndex;
					
					if(PRINT_DEBUG_MESSAGES) FPrint("Group %d, Customer %d has found the following seat: row %d and seat %d\n", 72, 4,
						myIndex*1000000 + customerIndex*10000 + smallestRowThatFits*100 + fillCol);
					
					/*/Decrement remaining seats, increment current customer*/
					needSeats--;
					customerIndex++;
				}
				
				fillCol++;
			}
		}
	}
	
	/*/Customer group successfully seated*/
	ReleaseLock(screeningRoomLock);
	if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: whole group successfully seated in theater\n", 57, 1, myIndex);
	
	/*/Wait for movie to start*/
	AcquireLock(movieInProgressLock);
	if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: waiting for movie to start...\n", 44, 1, myIndex);
	WaitCondition(movieInProgressCondition, movieInProgressLock);
	
	/*/Signalled by MovieTechnician that movie is over	*/
	ReleaseLock(movieInProgressLock);
	if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: Signalled by MovieTechnician that movie is over\n", 62, 1, myIndex);
	
	/*/Now that movie is over, wait for group to get out of their seats*/
	AcquireLock(screeningRoomLock);
	leavingSeatIndex = 0;
	for(c1 = 0; c1 < SCREENING_ROOM_COLS; c1++)
	{
		for(r1 = 0; r1 < SCREENING_ROOM_ROWS; r1++)
		{
			if(screeningRoomSeat[r1][c1] == myIndex)
			{
				if(PRINT_OUTPUT_MESSAGES) FPrint("Customer %d in group %d is getting out of a theater room seat.\n", 64, 2, leavingSeatIndex*100 + myIndex);
				if(PRINT_DEBUG_MESSAGES) FPrint("Group %d, Customer %d getting out of seat row %d, col %d\n", 58, 4, myIndex*1000000 + leavingSeatIndex*10000 + r1*100 + c1);
				
				screeningRoomSeat[r1][c1] = -1;
				leavingSeatIndex++;
				Yield();
			}
		}
	}
	ReleaseLock(screeningRoomLock);
	
	/*/================ Go To Bathroom ================*/
	
	/*/All follower Customers have exited their seats, ask if people want to go to the bathroom*/
	for(i8 = 0; i8 < myGroupSize; i8++)
	{
		/*/Randomly select bathroom*/
		bathroomWanted = 0;
		
		roll1 = RandInt() % 100 + 1;
		if(roll1 <= CUSTOMER_WANT_BATHROOM_PROBABILITY)
		{
			bathroomWanted = 1;
		}
		
		if(bathroomWanted == 1)
		{
			if(PRINT_OUTPUT_MESSAGES) FPrint("Customer %d in Group %d is going to the bathroom.\n", 51, 2, i8*100 + myIndex);
			if(PRINT_DEBUG_MESSAGES) FPrint("Group %d, Customer %d wants to go to the bathroom.\n", 52, 2, myIndex*100 + i8);
			
			Yield();
			
			if(PRINT_OUTPUT_MESSAGES) FPrint("Customer %d in Group %d is leaving the bathroom.\n", 50, 2, i8*100 + myIndex);
			if(PRINT_DEBUG_MESSAGES) FPrint("Group %d, Customer %d left the bathroom.\n", 42, 2, myIndex*100 + i8);
		}
		else
		{
			if(PRINT_DEBUG_MESSAGES) FPrint("Group %d, Customer %d does not want to go to the bathroom.\n", 60, 2, myIndex*100 + i8);
		}
	}
	
	if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: no more followers need to use the bathroom, proceeding to exit\n", 77, 1, myIndex);
	
	/*
	for(int i = 0; i < myGroupSize; i++)
	{
		followerCustomerInitLock -> Acquire();
		
		Thread* fc;
		fc = new Thread("FollowerCustomer");
		fc -> Fork(FollowerCustomer, i);
		
		followerCustomerInitCondition -> Wait();
		
		followerCustomerStartLock -> Acquire();
		followerCustomerStartLock -> Release();
	}
	
	followerCustomerStartLock -> Acquire();
	followerCustomerStartCondition -> Broadcast(followerCustomerStartLock);
	followerCustomerStartLock -> Release();
	*/
	
		
	/*/Customer exits theater and decrements count*/
	if(PRINT_DEBUG_MESSAGES) FPrint("Customer %d: leaving theater\n", 30, 1, myIndex);
	
	AcquireLock(numCustomersInTheaterLock);
	numCustomersInTheater -= myGroupSize;
	ReleaseLock(numCustomersInTheaterLock);
	
	AcquireLock(numGroupsInTheaterLock);
	numGroupsInTheater--;
	ReleaseLock(numGroupsInTheaterLock);
		
	for(i9 = 0; i9 < myGroupSize; i9++)
	{
		if(PRINT_OUTPUT_MESSAGES) FPrint("Customer %d in Group %d has exited the movie theater.\n", 55, 2, i9*100 + myIndex);
		Yield();
	}
	Exit(0);
}

/*/======== Ticket Clerk Function ========*/
void TicketClerk()
{
	int myIndex;





	AcquireLock(latestIndexLock);
	myIndex = latestIndex;
	SignalCondition(latestIndexCondition, latestIndexLock);
	ReleaseLock(latestIndexLock);


	if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: created\n", 25, 1, myIndex);
	AcquireLock(tcStateLock[myIndex]);
	tcState[myIndex] == CLERK_AVAILABLE;
	
	while(1)
	{
		/*/Wait for Customer's ticket order*/
		tcInteractionWaitLabel:
		if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: waiting for next Customer\n", 43, 1, myIndex);
		WaitCondition(tcInteractionCondition[myIndex], tcInteractionLock[myIndex]);
		
		if(tcState[myIndex] == CLERK_ON_BREAK)
		{
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: going on break...\n", 35, 1, myIndex);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: acquiring tcBreakLock %d\n", 42, 2, myIndex*100 + myIndex);
			AcquireLock(tcBreakLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: signalling tcInteractionLock %d\n", 49, 2, myIndex*100 + myIndex);
			SignalCondition(tcInteractionCondition[myIndex], tcInteractionLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: releasing tcInteractionLock %d\n", 48, 2, myIndex*100 + myIndex);
			ReleaseLock(tcInteractionLock[myIndex]);
			goto tcBreakLabel;
		}
		
		/*/After getting signalled by Customer with ticket order*/
		if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: acquiring tcInteractionLock %d\n", 48, 2, myIndex*100 + myIndex);
		AcquireLock(tcInteractionLock[myIndex]);
		
		tcState[myIndex] = CLERK_BUSY;
		if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: processing ticket order of size %d\n", 52, 2, myIndex*100 + numTicketsDesired[myIndex]);
		if(PRINT_OUTPUT_MESSAGES) FPrint("TicketClerk %d has an order for %d and the cost is %d.\n", 56, 3, 
			myIndex*10000 + numTicketsDesired[myIndex]*100 + numTicketsDesired[myIndex] * TICKET_PRICE);
		
		/*/Process ticket order and add to total*/
		AcquireLock(profitLock);
		totalTicketsSold[myIndex] += numTicketsDesired[myIndex];
		ReleaseLock(profitLock);
		
		/*/Signal Customer to complete transaction		*/
		if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: signalling Customer with completed order of size %d\n", 69, 2, myIndex*100 + numTicketsDesired[myIndex]);
		SignalCondition(tcInteractionCondition[myIndex], tcInteractionLock[myIndex]);
		
		if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: waiting for Customer to receive tickets\n", 57, 1, myIndex);
		WaitCondition(tcInteractionCondition[myIndex], tcInteractionLock[myIndex]);
		
		if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: Customer received tickets succesfully\n", 55, 1, myIndex);
		
		/*/Release state for manager to edit*/
		ReleaseLock(tcStateLock[myIndex]);
		
		/*/Finished dealing with customer, perhaps go on break*/
		AcquireLock(tcStateLock[myIndex]);
		if(tcState[myIndex] == CLERK_ON_BREAK)
		{
			if(PRINT_OUTPUT_MESSAGES) FPrint("TicketClerk %d is going on break.\n", 35, 1, myIndex);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: signalling Manager that I am going on break\n", 61, 1, myIndex);
			
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: acquiring tcBreakStopLock %d\n", 46, 2, myIndex*100 + myIndex);
			AcquireLock(tcBreakStopLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: acquiring tcBreakLock %d\n", 42, 2, myIndex*100 + myIndex);
			AcquireLock(tcBreakLock[myIndex]);
			
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: signalling tcBreakStopLock %d\n", 47, 2, myIndex*100 + myIndex);
			SignalCondition(tcBreakStopCondition[myIndex], tcBreakStopLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: releasing tcBreakStopLock %d\n", 46, 2, myIndex*100 + myIndex);
			ReleaseLock(tcBreakStopLock[myIndex]);
			
			tcBreakLabel:
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: releasing tcStateLock %d\n", 42, 2, myIndex*100 + myIndex);
			ReleaseLock(tcStateLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: waiting tcBreakLock %d\n", 40, 2, myIndex*100 + myIndex);
			WaitCondition(tcBreakCondition[myIndex], tcBreakLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: acquiring tcStateLock %d\n", 42, 2, myIndex*100 + myIndex);
			AcquireLock(tcStateLock[myIndex]);
			
			if(PRINT_OUTPUT_MESSAGES) FPrint("TicketClerk %d is coming off break.\n", 37, 1, myIndex);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: returning from break\n", 38, 1, myIndex);
			
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: acquiring tcInteractionLock %d\n", 48, 2, myIndex*100 + myIndex);
			AcquireLock(tcInteractionLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: signalling tcBreakLock %d\n", 43, 2, myIndex*100 + myIndex);
			SignalCondition(tcBreakCondition[myIndex], tcBreakLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: releasing tcBreakLock %d\n", 42, 2, myIndex*100 + myIndex);
			ReleaseLock(tcBreakLock[myIndex]);
			goto tcInteractionWaitLabel;
		}
		
		/*/Lock down lines before accepting next Customer*/
		if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: acquiring Lock for Customer search\n", 52, 1, myIndex);
		AcquireLock(tcLineManager);
		if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: acquiring tcInteractionLock %d\n", 48, 1, myIndex*100 + myIndex);
		AcquireLock(tcInteractionLock[myIndex]);
		
		/*/Check for customers in line*/
		if(tcLineLength[myIndex] > 0)
		{
			/*/I have a customer in line, set myself to busy and decrement line length*/
			if(PRINT_OUTPUT_MESSAGES) FPrint("TicketClerk %d has a line length %d and is signalling a customer.\n", 67, 2, myIndex*100 + tcLineLength[myIndex]);
			
			tcState[myIndex] = CLERK_BUSY;
			tcLineLength[myIndex]--;
			
			/*/Wake up 1 customer*/
			SignalCondition(tcLineCondition[myIndex], tcLineManager);
			
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: woke up next Customer\n", 39, 1, myIndex);
		}
		else
		{
			/*/No one in my line, set myself to available*/
			tcState[myIndex] = CLERK_AVAILABLE;
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: no Customers in line\n", 38, 1, myIndex);
			if(PRINT_OUTPUT_MESSAGES) FPrint("TicketClerk %d has no one in line.  I am available for a customer.\n", 68, 1, myIndex);
		}
		
		/*/Release and allow other Customers to search lines*/
		if(PRINT_DEBUG_MESSAGES) FPrint("TicketClerk %d: releasing Lock for Customer search\n", 52, 1, myIndex);
		ReleaseLock(tcLineManager);
	}
	/* 
	Exit(0);
	*/
}

/*/======== Concession Clerk Function ========*/
void ConcessionClerk()
{
	int myIndex;
	
	
	AcquireLock(latestIndexLock);
	myIndex = latestIndex;
	SignalCondition(latestIndexCondition, latestIndexLock);
	ReleaseLock(latestIndexLock);


	if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: created\n", 29, 1, myIndex);
	AcquireLock(ccStateLock[myIndex]);
	ccState[myIndex] == CLERK_AVAILABLE;
	
	while(1)
	{
		/*/Wait for Customer's food order*/
		ccInteractionWaitLabel:
		if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: waiting for next Customer\n", 47, 1, myIndex);
		WaitCondition(ccInteractionCondition[myIndex], ccInteractionLock[myIndex]);
		
		if(ccState[myIndex] == CLERK_ON_BREAK)
		{
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: going on break...\n", 39, 1, myIndex);
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: acquiring ccBreakLock %d\n", 46, 2, myIndex*100 + myIndex);
			AcquireLock(ccBreakLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: signalling ccInteractionLock %d\n", 53, 2, myIndex*100 + myIndex);
			SignalCondition(ccInteractionCondition[myIndex], ccInteractionLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: releasing ccInteractionLock %d\n", 52, 2, myIndex*100 + myIndex);
			ReleaseLock(ccInteractionLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: waiting ccBreakLock %d\n", 44, 2, myIndex*100 + myIndex);
			WaitCondition(ccBreakCondition[myIndex], ccBreakLock[myIndex]);
			goto ccBreakLabel;
		}
		
		/*/After getting signalled by Customer with food order*/
		if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: acquiring ccInteractionLock %d\n", 52, 2, myIndex*100 + myIndex);
		AcquireLock(ccInteractionLock[myIndex]);
		
		ccState[myIndex] = CLERK_BUSY;
		if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: processing %d popcorn and %d soda\n", 55, 3, myIndex*10000 + numPopcornDesired[myIndex]*100 + numSodaDesired[myIndex]);
		if(PRINT_OUTPUT_MESSAGES) FPrint("ConcessionClerk %d has an order for %d popcorn and %d soda.  The cost is %d.\n", 78, 4, 
				myIndex*1000000 + numPopcornDesired[myIndex]*10000 + numSodaDesired[myIndex]*100 + numPopcornDesired[myIndex] * POPCORN_PRICE + numSodaDesired[myIndex] * SODA_PRICE);
		
		/*/Process food order and add to total*/
		AcquireLock(profitLock);
		totalPopcornSold[myIndex] += numPopcornDesired[myIndex];
		totalSodaSold[myIndex] += numSodaDesired[myIndex];
		ReleaseLock(profitLock);
		
		/*/Signal Customer to complete transaction*/
		if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: signalling Customer with %d popcorn and %d soda\n", 69, 3, myIndex*10000 + numPopcornDesired[myIndex]*100 + numSodaDesired[myIndex]);
		SignalCondition(ccInteractionCondition[myIndex], ccInteractionLock[myIndex]);
		
		if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: waiting for Customer to receive food\n", 58, 1, myIndex);
		WaitCondition(ccInteractionCondition[myIndex], ccInteractionLock[myIndex]);
		
		if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: Customer received food succesfully\n", 56, 1, myIndex);
		
		/*/Release state for manager to edit*/
		if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: releasing ccStateLock %d\n", 46, 2, myIndex*100 + myIndex);
		ReleaseLock(ccStateLock[myIndex]);
		
		/*/Finished dealing with customer, perhaps go on break*/
		if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: releasing ccStateLock %d\n", 46, 2, myIndex*100 + myIndex);
		AcquireLock(ccStateLock[myIndex]);
		if(ccState[myIndex] == CLERK_ON_BREAK)
		{
			if(PRINT_OUTPUT_MESSAGES) FPrint("ConcessionClerk %d is going on break.\n", 39, 1, myIndex);
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: signalling Manager that I am going on break\n", 65, 1, myIndex);
			
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: acquiring ccBreakStopLock %d\n", 50, 2, myIndex*100 + myIndex);
			AcquireLock(ccBreakStopLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: acquiring ccBreakLock %d\n", 46, 2, myIndex*100 + myIndex);
			AcquireLock(ccBreakLock[myIndex]);
			
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: signalling ccBreakStopLock %d\n", 51, 2, myIndex*100 + myIndex);
			SignalCondition(ccBreakStopCondition[myIndex], ccBreakStopLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: release ccBreakStopLock %d\n", 48, 2, myIndex*100 + myIndex);
			ReleaseLock(ccBreakStopLock[myIndex]);
			
			ccBreakLabel:
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: releasing ccStateLock %d\n", 46, 2, myIndex*100 + myIndex);
			ReleaseLock(ccStateLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: waiting ccBreakLock %d\n", 44, 2, myIndex*100 + myIndex);
			WaitCondition(ccBreakCondition[myIndex], ccBreakLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: acquiring ccStateLock %d\n", 46, 2, myIndex*100 + myIndex);
			AcquireLock(ccStateLock[myIndex]);
			
			if(PRINT_OUTPUT_MESSAGES) FPrint("ConcessionClerk %d is coming off break.\n", 41, 1, myIndex);
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: returning from break\n", 42, 1, myIndex);
			
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: acquiring ccInteractionLock %d\n", 52, 2, myIndex*100 + myIndex);
			AcquireLock(ccInteractionLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: signalling ccBreakLock %d\n", 47, 2, myIndex*100 + myIndex);
			SignalCondition(ccBreakCondition[myIndex], ccBreakLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: releasing ccBreakLock %d\n", 46, 2, myIndex*100 + myIndex);
			ReleaseLock(ccBreakLock[myIndex]);
			goto ccInteractionWaitLabel;
		}
		
		/*/Lock down lines before accepting next Customer*/
		if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: acquiring Lock for Customer search\n", 56, 1, myIndex);
		AcquireLock(ccLineManager);
		AcquireLock(ccInteractionLock[myIndex]);
		
		/*/Check for customers in line*/
		if(ccLineLength[myIndex] > 0)
		{
			/*/I have a customer in line, set myself to busy and decrement line length*/
			if(PRINT_OUTPUT_MESSAGES) FPrint("ConcessionClerk %d has a line length %d and is signalling a customer.\n", 71, 2, myIndex*100 + tcLineLength[myIndex]);
			
			ccState[myIndex] = CLERK_BUSY;
			ccLineLength[myIndex]--;
			
			/*/Wake up 1 customer*/
			SignalCondition(ccLineCondition[myIndex], ccLineManager);
			
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: woke up next Customer\n", 43, 1, myIndex);
		}
		else
		{
			/*/No one in my line, set myself to available*/
			ccState[myIndex] = CLERK_AVAILABLE;
			if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: no Customers in line\n", 42, 1, myIndex);
			if(PRINT_OUTPUT_MESSAGES) FPrint("ConcessionClerk %d has no one in line.  I am available for a customer.\n", 72, 1, myIndex);
		}
		
		/*/Release and allow other Customers to search lines*/
		if(PRINT_DEBUG_MESSAGES) FPrint("ConcessionClerk %d: releasing Lock for Customer search\n", 56, 1, myIndex);
		ReleaseLock(ccLineManager);
	}
}

/*/======== Ticket Taker Function ========*/
void TicketTaker()
{
	int myIndex;


	AcquireLock(latestIndexLock);
	myIndex = latestIndex;
	SignalCondition(latestIndexCondition, latestIndexLock);
	ReleaseLock(latestIndexLock);
	

	if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: created\n", 25, 1, myIndex);
	AcquireLock(ttStateLock[myIndex]);
	ttState[myIndex] == CLERK_AVAILABLE;
	
	while(1)
	{
		if(ticketTakerFull[myIndex])
		{
			/*/Wait for next movie to start before resuming ticket taking*/
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Waiting for next movie before resuming ticket taking\n", 70, 1, myIndex);
			AcquireLock(beginTakingTicketsLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: waiting on beginTakingTicketsLock\n", 51, 1, myIndex);
			ttWaitBeginTakingTickets: WaitCondition(beginTakingTicketsCondition[myIndex], beginTakingTicketsLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: signalled out of beginTakingTicketsCondition\n", 62, 1, myIndex);
			
			/*/ticketTakerFullLock -> Acquire();*/
			ticketTakerFull[myIndex] = 0;
			ttForcedToStop[myIndex] = 0;
			ttState[myIndex] = CLERK_AVAILABLE;
			/*/ticketTakerFullLock -> Release();*/
			
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Acquiring ttInteractionLock[%d]\n", 49, 2, myIndex*100 + myIndex);
			AcquireLock(ttInteractionLock[myIndex]);
			
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: signalling beginTakingTicketsCondition %d\n", 59, 2, myIndex*100 + myIndex);
			SignalCondition(beginTakingTicketsCondition[myIndex], beginTakingTicketsLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: releasing beginTakingTicketsLock\n", 50, 1, myIndex);
			ReleaseLock(beginTakingTicketsLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Ready to resume ticket taking\n", 47, 1, myIndex);
			/*/ttInteractionCondition[myIndex] -> Wait(ttInteractionLock[myIndex]);*/
			/*/ttInteractionLock[myIndex] -> Release();*/
		}
		
		/*/Wait for the Customer's tickets*/
		ttInteractionWaitLabel:
		if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: waiting for next Customer\n", 43, 1, myIndex);
		WaitCondition(ttInteractionCondition[myIndex], ttInteractionLock[myIndex]);
		
		if(ttState[myIndex] == CLERK_ON_BREAK)
		{
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: going on break...\n", 35, 1, myIndex);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: acquiring ttBreakLock %d\n", 42, 2, myIndex*100 + myIndex);
			AcquireLock(ttBreakLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: signalling ttInteractionLock %d\n", 49, 2, myIndex*100 + myIndex);
			SignalCondition(ttInteractionCondition[myIndex], ttInteractionLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: releasing ttInteractionLock %d\n", 48, 2, myIndex*100 + myIndex);
			ReleaseLock(ttInteractionLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: waiting ttBreakLock %d\n", 40, 2, myIndex*100 + myIndex);
			WaitCondition(ttBreakCondition[myIndex], ttBreakLock[myIndex]);
			goto ttBreakLabel;
		}
		
		/*/At this point, check to see if you were woken up by a customer, or by a manager*/
		if(ttForcedToStop[myIndex])
		{
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Woken up by Manager for Stop\n", 46, 1, myIndex);
			
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: acquiring beginTakingTicketLock %d\n", 52, 2, myIndex*100 + myIndex);
			AcquireLock(beginTakingTicketsLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: signalling ttInteractionLock %d\n", 49, 2, myIndex*100 + myIndex);
			SignalCondition(ttInteractionCondition[myIndex], ttInteractionLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Releasing ttInteractionLock[%d]\n", 49, 2, myIndex*100 + myIndex);
			ReleaseLock(ttInteractionLock[myIndex]);
			goto ttWaitBeginTakingTickets;
		}
		else
		
		{
			/*/After getting signalled by Customer with tickets		*/
			ttState[myIndex] = CLERK_BUSY;
			
			/*/Check if there is room in screening room*/
			AcquireLock(ticketCountBoxLock);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: ticketCountBox currently has %d tickets\n", 57, 2, myIndex*100 + ticketCountBox);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: processing %d incoming tickets from Customer\n", 62, 2, myIndex*100 + numTicketsGiven[myIndex]);
			if(PRINT_OUTPUT_MESSAGES)FPrint("TicketClerk %d has received %d tickets.\n", 41, 2, myIndex*100 + numTicketsGiven[myIndex]);
			
			AcquireLock(ticketTakerFullLock);
			
			if((ticketTakerFull[myIndex]) || (ticketCountBox + numTicketsGiven[myIndex] > SCREENING_ROOM_CAPACITY))
			{
					
				/*/Lock the lines so that no Customer tries to join while TicketTaker gets full*/
				/*/ttLineManager -> Acquire();*/
				/*/If the Customer's group is too large, reject him from seating*/
				if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Not enough room for Customer!\n", 47, 1, myIndex);
				if(PRINT_OUTPUT_MESSAGES) FPrint("TicketTaker %d is not allowing the group into theater.  The number of taken tickets is %d and the group size is %d.\n", 117, 3,
					myIndex*10000 + ticketCountBox*100 + numTicketsGiven[myIndex]);
					
				ticketTakerFull[myIndex] = 1;
				ticketTakerSaidToProceed[myIndex] = 0;
				
				if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: set myself to full, releasing ticketTakerFullLock\n", 67, 1, myIndex);
				if(PRINT_OUTPUT_MESSAGES) FPrint("Ticketaker %d has stopped taking tickets.\n", 43, 1, myIndex);
				
				/*/ttLineManager -> Release();*/
				ReleaseLock(ticketTakerFullLock);
				ReleaseLock(ticketCountBoxLock);
				
				/*/Signal current Customer with response*/
				if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Signalling current Customer to go to lobby\n", 60, 1, myIndex);
				SignalCondition(ttInteractionCondition[myIndex], ttInteractionLock[myIndex]);
				if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Releasing ttInteractionLock[%d]\n", 49, 2, myIndex*100 + myIndex);
				ReleaseLock(ttInteractionLock[myIndex]);
				/*/Wait for Customer signal*/
				if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Waiting for Customer to go to lobby\n", 53, 1, myIndex);
				if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Acquiring ttLobbyLock %d\n", 42, 2, myIndex*100 + myIndex);
				AcquireLock(ttLobbyLock[myIndex]);
				
				if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Customer went to lobby succesfully\n", 52, 1, myIndex);
				if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Releasing ttLobbyLock %d\n", 42, 2, myIndex*100 + myIndex);
				ReleaseLock(ttLobbyLock[myIndex]);
			}
			else
			{
				ReleaseLock(ticketTakerFullLock);
				
				/*/If the Customer's group can fit, accept him for seating and add tickets to total*/
				if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: There is room for Customer, adding %d tickets to box.\n", 71, 2, myIndex*100 + numTicketsGiven[myIndex]);
				if(PRINT_OUTPUT_MESSAGES) FPrint("TicketTaker %d is allowing the group into the theater.  The number of tickets taken is %d.\n", 92, 2,
					myIndex*100 + numTicketsGiven[myIndex]);
					
				ticketTakerSaidToProceed[myIndex] = 1;
				ticketCountBox += numTicketsGiven[myIndex];	
				
				if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: New ticket box total: %d\n", 42, 2, myIndex*100 + ticketCountBox);
				ReleaseLock(ticketCountBoxLock);
				
				/*/Signal current Customer with response*/
				if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Signalling current Customer to go to screening room\n",69, 1, myIndex);
				SignalCondition(ttInteractionCondition[myIndex], ttInteractionLock[myIndex]);
				
				/*/Wait for Customer response */
				if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Waiting for Customer to go to screening room\n", 62, 1, myIndex);
				WaitCondition(ttInteractionCondition[myIndex], ttInteractionLock[myIndex]);
				
				if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Customer went to screening room succesfully\n", 61, 1, myIndex);
			}
		}
		
		/*/Release state for manager to edit*/
		if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Releasing ttStateLock\n", 39, 1, myIndex);
		ReleaseLock(ttStateLock[myIndex]);
		
		/*/Finished dealing with Customer*/
		if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Acquiring ttStateLock\n", 39, 1, myIndex);
		AcquireLock(ttStateLock[myIndex]);
		
		if(ttForcedToStop[myIndex])
		{
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Forced to Stop\n", 32, 1, myIndex);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: stop acq\n", 26, 1, myIndex);
			AcquireLock(ttStopLock);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: b acq\n", 23, 1, myIndex);
			AcquireLock(beginTakingTicketsLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: stop sig\n", 26, 1, myIndex);
			SignalCondition(ttStopCondition, ttStopLock);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: stop wait\n", 27, 1, myIndex);
			WaitCondition(ttStopCondition, ttStopLock);
			ReleaseLock(ttStopLock);
			
			goto ttWaitBeginTakingTickets;
			/*
			if(PRINT_DEBUG_MESSAGES) printf("TicketTaker %d: b wait\n", myIndex);
			beginTakingTicketsCondition[myIndex] -> Wait(beginTakingTicketsLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) printf("TicketTaker %d: signalled out of beginTakingTicketsCondition\n", myIndex);
				
			//ticketTakerFullLock -> Acquire();
			ticketTakerFull[myIndex] = 0;
			//ticketTakerFullLock -> Release();
			
			ttInteractionLock[myIndex] -> Acquire();
			
			if(PRINT_DEBUG_MESSAGES) printf("TicketTaker %d: signalling beginTakingTicketsCondition\n", myIndex);
			beginTakingTicketsCondition[myIndex] -> Signal(beginTakingTicketsLock[myIndex]);
			beginTakingTicketsLock[myIndex] -> Release();
			if(PRINT_DEBUG_MESSAGES) printf("TicketTaker %d: Ready to resume ticket taking\n", myIndex);
			//ttInteractionCondition[myIndex] -> Wait(ttInteractionLock[myIndex]);
			//ttInteractionLock[myIndex] -> Release();
				*/	
		
		}
		
		
		
		if(ttState[myIndex] == CLERK_ON_BREAK)
		{
			if(PRINT_OUTPUT_MESSAGES) FPrint("TicketTaker %d is going on break.\n", 35, 1, myIndex);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: signalling Manager that I am going on break\n", 61, 1, myIndex);
						
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: acquiring ttBreakStopLock %d\n", 46, 2, myIndex*100 + myIndex);
			AcquireLock(ttBreakStopLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: acquiring ttBreakLock %d\n", 42, 2, myIndex*100 + myIndex);
			AcquireLock(ttBreakLock[myIndex]);
			
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: signalling ttBreakStopLock %d\n", 47, 2, myIndex*100 + myIndex);
			SignalCondition(ttBreakStopCondition[myIndex], ttBreakStopLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: releasing ttBreakStopLock %d\n", 46, 2, myIndex*100 + myIndex);
			ReleaseLock(ttBreakStopLock[myIndex]);
			
			ttBreakLabel:
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: acquiring ttStateLock %d\n", 42, 2, myIndex*100 + myIndex);
			ReleaseLock(ttStateLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: waiting ttBreakLock %d\n", 40, 2, myIndex*100 + myIndex);
			WaitCondition(ttBreakCondition[myIndex], ttBreakLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: acquiring ttStateLock %d\n", 42, 2, myIndex*100 + myIndex);
			AcquireLock(ttStateLock[myIndex]);
			
			if(PRINT_OUTPUT_MESSAGES) FPrint("TicketTaker %d is coming off break.\n", 37, 1, myIndex);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: returning from break\n", 38, 1, myIndex);
			
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: acquiring ttInteractionLock %d\n", 48, 2, myIndex*100 + myIndex);
			AcquireLock(ttInteractionLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: signalling ttBreakLock %d\n", 43, 2, myIndex*100 + myIndex);
			SignalCondition(ttBreakCondition[myIndex], ttBreakLock[myIndex]);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: releasing ttBreakLock %d\n", 42, 2, myIndex*100 + myIndex);
			ReleaseLock(ttBreakLock[myIndex]);
			goto ttInteractionWaitLabel;
		}
		
		/*/If we are full, exit loop and go to top*/
		if(!ticketTakerFull[myIndex])
		{
			/*/Lock down lines before accepting next Customer*/
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: acquiring ttLineManager\n", 41, 1, myIndex);
			AcquireLock(ttLineManager);
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: Acquiring ttInteractionLock[%d]\n", 49, 2, myIndex*100 + myIndex);
			AcquireLock(ttInteractionLock[myIndex]);
			
			/*/Check for customers in line*/
			if(ttLineLength[myIndex] > 0)
			{
				if(PRINT_OUTPUT_MESSAGES) FPrint("TicketTaker %d has a line length %d and is signalling a customer.\n", 67, 2, myIndex*100 + tcLineLength[myIndex]);
			
				/*/Customers are in line, set state to busy and decrement line length*/
				ttState[myIndex] = CLERK_BUSY;
				ttLineLength[myIndex]--;
				
				/*/Wake up next customer*/
				SignalCondition(ttLineCondition[myIndex], ttLineManager);
				
				if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: woke up next Customer\n", 39, 1, myIndex);
			}
			else
			{
				/*/No Customers in line, set state to available*/
				ttState[myIndex] = CLERK_AVAILABLE;
				if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: no Customers in line\n", 38, 1, myIndex);
				if(PRINT_OUTPUT_MESSAGES) FPrint("TicketClerk %d has no one in line.  I am available for a customer.\n", 68, 1, myIndex);
			}
			
			/*/Release and allow other Customers to search lines*/
			if(PRINT_DEBUG_MESSAGES) FPrint("TicketTaker %d: releasing ttLineManager\n", 41, 1, myIndex);
			ReleaseLock(ttLineManager);
		}
	}
}

/*/======== Manager Function ========*/
void Manager()
{
	int myIndex;
	int loops;
	int activeTicketTakers;
	int activeTicketTakers1;
	int tcRevenue;
	int concRevenue;
	int nextTcRevenue;
	int nextConcRevenue;
	
	int longestLineLength;
	int longestLineIndex;
	
	int shortLineIndex;
	
	/* Counters */
	int i0;
	int i1;
	int i2;
	int i3;
	int i4;
	int i5;
	int i6;
	int i7;
	int i8;
	int i9;
	int i10;
	int i11;
	int i12;
	int i13;
	
	int i14;
	int i15;
	int i16;
	
	int j0;
	int j1;
	int j2;
	int j3;
	int j4;
	
	int k0;
	int k1;
	int k2;

	myIndex = 0;
	
	if(PRINT_DEBUG_MESSAGES) FPrint("Manager created\n", 17, 0, 0);
	AcquireLock(numCustomersInTheaterLock);
	
	loops = 0;
	
	do
	{
		
		ReleaseLock(numCustomersInTheaterLock);
		for(i0 = 0; i0 < 10; i0++){
		Yield();
		}
		if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Loop #%d\n", 19, 1, loops);
		loops++;
		if(PRINT_DEBUG_MESSAGES && MOVIE_STATE == ROOM_EMPTY) FPrint("Manager: Movie state is ROOM_EMPTY\n", 36, 0, 0);
		if(PRINT_DEBUG_MESSAGES && MOVIE_STATE == ACCEPTING_TICKETS) FPrint("Manager: Movie state is ACCEPTING_TICKETS\n", 43, 0, 0);
		if(PRINT_DEBUG_MESSAGES && MOVIE_STATE == CUSTOMER_CUTOFF) FPrint("Manager: Movie state is CUSTOMER_CUTOFF\n", 41, 0, 0);
		if(PRINT_DEBUG_MESSAGES && MOVIE_STATE == IN_PROGRESS) FPrint("Manager: Movie state is IN_PROGRESS\n", 37, 0, 0);
		if(PRINT_DEBUG_MESSAGES && MOVIE_STATE == ROOM_EMPTYING) FPrint("Manager: Movie state is ROOM_EMPTYING\n", 39, 0, 0);
		/*
	
		
	
		STATES
	
		ROOM_EMPTY: movie has ended, screening room is empty (initial state, also set by movie tech). manager can randomly decide to start next movie.
		when he does, he activates the takers, announces to the lobby and changes the state to...

		ACCEPTING_TICKETS: customers are handing tickets to ticket takers. this goes on until all ticket takers are full. ticket takers can also be randomly
		set to full by the manager when he feels like it. whenever a taker is full, his line is disbanded. when manager detects that all ticket
		takers are full he changes the state to:

		CUSTOMER_CUTOFF: ticket takers are deactivated, customers are filling the seats. this goes on until the number in the ticket countbox matches the
		number of seated people in the theater. when this happens the movie tech changes state and yields for a while

		IN_PROGRESS: movie tech is yielding. when the yield ends, first thing he does is change the state to...

		ROOM_EMPTYING: movie tech busy loops waiting for the number of seated people to hit zero. when this occurs he changes the state back to BEGIN
	
	
	
		
	
		//if in ROOM_EMPTY state and loop multiple of XXXX
		//roll to see if you want to start taking customers. if so:
		//activate ticket takers. wait until they have all been successfully activated
		//broadcast to the lobby so customers bum-rush the ticket takers
		//set state to ACCEPTING_TICKETS, yield certain number of times (to prevent accepting state from not lasting long enough)
		
		*/
		if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Acquiring movieStateLock\n", 35, 0, 0);
		AcquireLock(movieStateLock);
		if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Acquired movieStateLock\n", 34, 0, 0);
		if((MOVIE_STATE == ROOM_EMPTY) && ((loops % MANAGER_DELAY_ACCEPTING) == 0))
		{
			if((RandInt() % 101) <= MANAGER_ROLL_ACCEPT)
			{
				if(PRINT_DEBUG_MESSAGES) FPrint("Manager has decided to start the movie process!\n", 49, 0, 0);
				
				for(i1 = 0; i1 < NUM_TICKET_TAKERS; i1++)
				{
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Activating Ticket Taker %d \n", 38, 1, i1);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: acquiring beginTakingTickets\n", 39, 0, 0);
					AcquireLock(beginTakingTicketsLock[i1]);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Signalling beginTakingTickets\n", 40, 0, 0);
					SignalCondition(beginTakingTicketsCondition[i1], beginTakingTicketsLock[i1]);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Waiting beginTakingTickets %d\n", 40, 1, i1);
					WaitCondition(beginTakingTicketsCondition[i1], beginTakingTicketsLock[i1]);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Releasing beginTakingTicketsLock[%d]\n", 47, 1, i1);
					ReleaseLock(beginTakingTicketsLock[i1]);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Acquiring ttInteractionLock[%d]\n", 42, 1, i1);
					AcquireLock(ttInteractionLock[i1]);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Releasing ttInteractionLock[%d]\n", 42, 1, i1);
					ReleaseLock(ttInteractionLock[i1]);
				}
				/*
				for(int i = 0; i < NUM_TICKET_TAKERS; i++)
				{
					if(ttState[i] != CLERK_ON_BREAK && ticketTakerFull[i])
					{
						if(PRINT_DEBUG_MESSAGES) printf("Manager acquiring beginTakingTicketsLock\n");
						beginTakingTicketsLock -> Acquire();
						//Signal to begin taking tickets
						if(PRINT_DEBUG_MESSAGES) printf("Manager signaling beginTakingTicketsLock\n");
						beginTakingTicketsCondition -> Signal(beginTakingTicketsLock);
						//Wait for confirmation
						if(PRINT_DEBUG_MESSAGES) printf("Manager waiting beginTakingTicketsLock\n");
						beginTakingTicketsCondition -> Wait(beginTakingTicketsLock);
						beginTakingTicketsLock -> Release();
					}
				
				
				
				}
				*/
				
				/*beginTakingTicketsLock -> Acquire();			
				beginTakingTicketsCondition -> Broadcast(beginTakingTicketsLock);
				beginTakingTicketsLock -> Release();
			
				int readyTicketTakers;
				do
				{
					readyTicketTakers = 0;
					int i = 0;
					for(i; i < NUM_TICKET_TAKERS; i++)
					{
						ticketTakerFullLock -> Acquire();
						if(!ticketTakerFull[i])
						{
							readyTicketTakers++;
						}
						ticketTakerFullLock -> Release();
					}
					if(PRINT_DEBUG_MESSAGES) printf("Manager: %d out of %d Ticket Takers are ready to take tickets.\n", readyTicketTakers, NUM_TICKET_TAKERS);
				}
				while(readyTicketTakers < NUM_TICKET_TAKERS);
				*/
				if(PRINT_DEBUG_MESSAGES) FPrint("Manager: All Ticket Takers are ready to take tickets.\n", 55, 0, 0);
				
				/*/Note: this for loop goes to NUM_TICKET_TAKERS + 1 to account for the extra lobby for Customers who found no TicketTakers*/
				for(i2 = 0; i2 < NUM_TICKET_TAKERS + 1; i2++)
				{
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Acquiring ttLobbyLock %d\n", 35, 1, i2);
					AcquireLock(ttLobbyLock[i2]);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Broadcasting to ttLobbyLock %d\n", 41, 1, i2);
					BroadcastCondition(ttLobbyCondition[i2], ttLobbyLock[i2]);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Releasing ttLobbyLock %d\n", 35, 1, i2);
					ReleaseLock(ttLobbyLock[i2]);
				}
				
				MOVIE_STATE = ACCEPTING_TICKETS;
				loops = 0;
				
				for(i3 = 0; i3 < MANAGER_YIELD_ACCEPTING; i3++)
				{
					Yield();
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Yield #%d\n", 20, 1, i3);
				}
			
			}
			else
			{
				if(PRINT_DEBUG_MESSAGES) FPrint("Manager has decided to NOT start the movie process right now!\n", 63, 0, 0);
			}
		}
		/*
		//if in ACCEPTING_TICKETS state (any loop multiple, but this is implicit)
		//iterate through fullness of ticket takers
		//if it's full, disband their line (do we need a local variable to track that we've already disbanded it to prevent doing it again?)
		//check if in loop multiple of XXXXX
		//if so, force them all to be full
		//(any loop) if there are no active ticket takers (full and break are inactive), tell movie tech to start movie. change state to CUSTOMER_CUTOFF (and reset the local array of inteans for line disbands)
		*/
		if(MOVIE_STATE == ACCEPTING_TICKETS)
		{
			/*
			//if(PRINT_DEBUG_MESSAGES) printf("Manager: Acquiring ticketTakerFullLock\n");
			//ticketTakerFullLock -> Acquire();
			*/
			/*
			for(int i = 0; i < NUM_TICKET_TAKERS; i++)
			{
			if(PRINT_DEBUG_MESSAGES) printf("Manager: Acquiring ttStateLock[%d]\n", i);
			ttStateLock[i] -> Acquire();
			}
			*/
			
			activeTicketTakers = 0;
			/*
			//maybe force ticket takers to be full
			//for all full ticket takers, disband their lines
			*/
			for(i4 = 0; i4 < NUM_TICKET_TAKERS; i4++)
			{
				if((loops % MANAGER_DELAY_CUTOFF == 0) && (ttState[i4] != CLERK_ON_BREAK) && (!ticketTakerFull[i4]))
				{
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Forcing TicketTaker %d to stop taking tickets\n", 56, 1, i4);
					/*/force this active clerk to be full.*/
					
					AcquireLock(ttLineManager);
					if(ttState[i4] == CLERK_AVAILABLE)
					{
						ttForcedToStop[i4] = 1;
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Acquiring ttInteractionLock[%d]\n", 42, 1, i4);
						AcquireLock(ttInteractionLock[i4]);
						SignalCondition(ttInteractionCondition[i4], ttInteractionLock[i4]);
						WaitCondition(ttInteractionCondition[i4], ttInteractionLock[i4]);
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Releasing ttInteractionLock[%d]\n", 42, 1, i4);
						ReleaseLock(ttInteractionLock[i4]);
						AcquireLock(beginTakingTicketsLock[i4]);
						ReleaseLock(beginTakingTicketsLock[i4]);
						ReleaseLock(ttLineManager);
					}
					else
					{
					ReleaseLock(ttLineManager);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Acquiring ttStateLock %d\n", 35, 1, i4);
					AcquireLock(ttStateLock[i4]);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Setting TicketTaker %d's global stop intean to 1\n", 63, 1, i4);
					ttForcedToStop[i4] = 1;
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Acquiring ttStopLock\n", 31, 0, 0);
					AcquireLock(ttStopLock);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Releasing ttStateLock %d\n", 35, 1, i4);
					ReleaseLock(ttStateLock[i4]);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Waiting for ttStopCondition on ttStopLock\n", 52, 0, 0);
					WaitCondition(ttStopCondition, ttStopLock);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Signalling ttStopCondition on ttStopLock\n", 51, 0, 0);
					SignalCondition(ttStopCondition, ttStopLock);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Releasing ttStopLock\n", 31, 0, 0);
					ReleaseLock(ttStopLock);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Acquiring beginTakingTickstLock %d\n", 45, 1, i4);
					AcquireLock(beginTakingTicketsLock[i4]);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Releasing beginTakingTicketsLock %d\n", 46, 1, i4);
					ReleaseLock(beginTakingTicketsLock[i4]);
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: TicketTaker %d has been forced to be stop taking tickets\n", 67, 1, i4);
					/*/at this point, the tickettaker has executed beginTakingTicketsCondition -> Wait(beginTakingTicketsLock)*/
					
					
					
					/*
					if(PRINT_DEBUG_MESSAGES) printf("Manager: Forcing Ticket Taker %d to be FULL\n", i);
					ticketTakerFull[i] = 1;*/
					}
				}
			
				if(ticketTakerFull[i4] || ttForcedToStop[i4])
				{
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Ticket Taker %d is FULL\n", 34, 1, i4);
					/*/disband their line*/
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Acquiring ttLineManager\n", 34, 0, 0);
					AcquireLock(ttLineManager);
					BroadcastCondition(ttLineCondition[i4], ttLineManager);
					ttLineLength[i4] = 0;
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Releasing ttLineManager\n", 34, 0, 0);
					ReleaseLock(ttLineManager);
				}
				else if(ttState[i4] != CLERK_ON_BREAK) /*/ not full, not on break == active*/
				{
					activeTicketTakers++;
				}
			}
			
			/*
			for(int i = 0; i < NUM_TICKET_TAKERS; i++)
			{
			if(PRINT_DEBUG_MESSAGES) printf("Manager: Releasing ttStateLock[%d]\n", i);
			ttStateLock[i] -> Release();
			}
			*/
			if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Active ticket takers: %d\n", 35, 1, activeTicketTakers);
			/*
			//if(PRINT_DEBUG_MESSAGES) printf("Manager: Releasing ticketTakerFullLock\n");
			//ticketTakerFullLock -> Release();
			
			//if all ticket takers are full its time to go to next phase
			
			*/
			
			if(activeTicketTakers == 0)
			{
			/*
			//make sure all ticket takers are not dealing with customers
			//signal movie tech
				//if(PRINT_DEBUG_MESSAGES) printf("Manager: Acquiring ticketTakerFullLock\n");
				//ticketTakerFullLock -> Acquire();
				
				/*
				for(int i = 0; i < NUM_TICKET_TAKERS; i++)
				{
					if(PRINT_DEBUG_MESSAGES) printf("Manager: Acquiring ttStateLock[%d]\n", i);
					ttStateLock[i] -> Acquire();
				}
				*/
				if(PRINT_DEBUG_MESSAGES) FPrint("Manager: acquiring movieTechLock\n", 34, 0, 0);
				AcquireLock(movieTechLock);
				MOVIE_STATE = CUSTOMER_CUTOFF;
				if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Signalling MovieTechnician to start movie when all Customers are seated.\n", 83, 0, 0);
				if(PRINT_OUTPUT_MESSAGES) FPrint("Manager is telling the MovieTechnnician to start the movie.\n", 61, 0, 0);
				SignalCondition(movieTechCondition, movieTechLock);
				if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Releasing movieTechLock\n", 34, 0, 0);
				ReleaseLock(movieTechLock);
				
				/*
				for(int i = 0; i < NUM_TICKET_TAKERS; i++)
				{
					if(PRINT_DEBUG_MESSAGES) printf("Manager: Releasing ttStateLock[%d]\n", i);
					ttStateLock[i] -> Release();
				}*//*
				//if(PRINT_DEBUG_MESSAGES) printf("Manager: Releasing ticketTakerFullLock\n");
				//ticketTakerFullLock -> Release();*/
			}
			/*
			//if(PRINT_DEBUG_MESSAGES) printf("Manager: Releasing ticketTakerFullLock\n");
			//ticketTakerFullLock -> Release();*/
		}
		
		
		ReleaseLock(movieStateLock);
		/*
		//if loop multiple of XXXX
		//process profits
		*/
		if((loops % MANAGER_DELAY_PROFITS) == 0)
		{
			if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Processing Profits\n", 29, 0, 0);
			if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Acquiring profitLock\n", 31, 0, 0);
			AcquireLock(profitLock);
			
			tcRevenue = 0;
			concRevenue = 0;
			
			for(i5 = 0; i5 < NUM_TICKET_CLERKS; i5++)
			{
				if(PRINT_DEBUG_MESSAGES) FPrint("Manager: totalTicketsSold[%d] = %d\n", 36, 2, i5*100 + totalTicketsSold[i5]);
				nextTcRevenue = totalTicketsSold[i5] * TICKET_PRICE;
				tcRevenue += nextTcRevenue;
				if(PRINT_DEBUG_MESSAGES) FPrint("Manager: tcRevenue = $%d%d\n", 28, 2, tcRevenue);
				
				if(PRINT_OUTPUT_MESSAGES) FPrint("Manager collected $%d%d from TicketClerk %d.\n", 46, 3, nextTcRevenue*100 + i5);
			}
			
			for(i6 = 0; i6 < NUM_CONCESSION_CLERKS; i6++)
			{
				nextConcRevenue = 0;
				nextConcRevenue += totalPopcornSold[i6] * POPCORN_PRICE;
				nextConcRevenue += totalSodaSold[i6] * SODA_PRICE;
				concRevenue += nextConcRevenue;
				if(PRINT_DEBUG_MESSAGES) FPrint("Manager: concRevenue = $%d%d\n", 30, 2, concRevenue);
				
				if(PRINT_OUTPUT_MESSAGES) FPrint("Manager collected $%d%d from ConcessionClerk %d.\n", 50, 3, nextConcRevenue*100 + i6);
			}
			
			if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Ticket Clerk Revenue: $%d%d\n", 38, 2, tcRevenue);
			if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Concessions Revenue: $%d%d\n", 37, 2, concRevenue);
			if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Total Revenue $%d%d\n", 30, 2, tcRevenue + concRevenue);
			
			if(PRINT_OUTPUT_MESSAGES) FPrint("Manager total money made by theater = %d%d\n", 44, 2, tcRevenue + concRevenue);			
			
			if(PRINT_DEBUG_MESSAGES) FPrint("Manager: Releasing profitLock\n", 31, 0, 0);
			ReleaseLock(profitLock);
		}
		
		/*
		          BREAK STUFF. ACQUIRE ALL STATE LOCKS
		if(PRINT_DEBUG_MESSAGES) printf("Manager: Acquiring all state locks for break processing\n");
		for(int i = 0; i < NUM_TICKET_CLERKS; i++)
		{
			tcStateLock[i] -> Acquire();
		}
		
		for(int i = 0; i < NUM_CONCESSION_CLERKS; i++)
		{
			ccStateLock[i] -> Acquire();
		}
		
		for(int i = 0; i < NUM_TICKET_TAKERS; i++)
		{
			ttStateLock[i] -> Acquire();
		}
		if(PRINT_DEBUG_MESSAGES) printf("Manager: Finished acquiring all state locks\n");
		*/
		
		
		/*
		//on any loop
		//process taking people off break
		*/
		if(ENABLE_BREAKS)
		{
			if(tcsOnBreak > 0)
			{
				if(PRINT_DEBUG_MESSAGES)
				 FPrint("Manager acquiring tcLineManager lock\n", 38, 0, 0);
				AcquireLock(tcLineManager);
				longestLineLength = -1;
				longestLineIndex = -1;
				
				
				/*/find longest line of a clerk that is not on break*/
				for(i7 = 0; i7 < NUM_TICKET_CLERKS; i7++)
				{	
					if((tcState[i7] != CLERK_ON_BREAK) && (tcLineLength[i7] > longestLineLength))
					{
						longestLineLength = tcLineLength[i7];
						longestLineIndex = i7;
					}
				}
				
				if(longestLineLength > MANAGER_LONGLINE)
				{/*
					//find someone to take off break
					//take them off break
					//disband longest line*/
							
					for(i8 = 0; i8 < NUM_TICKET_CLERKS; i8++)
					{
						if(tcState[i8] == CLERK_ON_BREAK)
						{			
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager acquiring tcBreakLock%d\n", 33, 1,i8);
							AcquireLock(tcBreakLock[i8]);
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager signal tcBreakCondition%d\n", 35, 1,i8);
							SignalCondition(tcBreakCondition[i8], tcBreakLock[i8]);
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager waiting on tcBreakCondition%d\n", 39, 1, i8);
							WaitCondition(tcBreakCondition[i8], tcBreakLock[i8]);
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager signalled awake on tcBreakCondition%d and releasing\n", 61, 1, i8);
							ReleaseLock(tcBreakLock[i8]);
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager acquiring tcInterationLock%d\n", 38, 1, i8);
							AcquireLock(tcInteractionLock[i8]);
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager releasing tcInteractionLock%d\n", 39, 1, i8);
							ReleaseLock(tcInteractionLock[i8]);
							tcState[i8] = CLERK_AVAILABLE;
							tcsOnBreak--;						
							break;
						}
					}
						/*/disband longest line*/
						if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager broadcasting tcLineCondition%d\n", 40, 1, longestLineIndex);
						BroadcastCondition(tcLineCondition[longestLineIndex], tcLineManager);
						tcLineLength[longestLineIndex] = 0;
				}
				if(PRINT_DEBUG_MESSAGES)
					FPrint("Manager releasing tcLineManager lock\n", 38, 0, 0);
				ReleaseLock(tcLineManager);
			}
			
			
			
			if(ccsOnBreak > 0)
			{
				if(PRINT_DEBUG_MESSAGES)
					FPrint("Manager acquiring ccLineManager lock\n", 38, 0, 0);
				AcquireLock(ccLineManager);
				longestLineLength = -1;
				longestLineIndex = -1;
				
				/*/find longest line of a clerk that is not on break*/
				for(i9 = 0; i9 < NUM_CONCESSION_CLERKS; i9++)
				{	
					if((ccState[i9] != CLERK_ON_BREAK) && (ccLineLength[i9] > longestLineLength))
					{
						longestLineLength = ccLineLength[i9];
						longestLineIndex = i9;
					}
				}
				
				if(longestLineLength > MANAGER_LONGLINE)
				{/*
					//find someone to take off break
					//take them off break
					//disband longest line*/
							
					for(i10 = 0; i10 < NUM_CONCESSION_CLERKS; i10++)
					{
						if(ccState[i10] == CLERK_ON_BREAK)
						{			
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager acquiring ccBreakLock%d\n", 33, 1, i10);
							AcquireLock(ccBreakLock[i10]);
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager signalling ccBreakCondition%d\n", 39, 1, i10);
							SignalCondition(ccBreakCondition[i10], ccBreakLock[i10]);
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager waiting on ccBreakCondition%d\n", 39, 1, i10);
							WaitCondition(ccBreakCondition[i10], ccBreakLock[i10]);
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager signalled awake and realeasing ccBreakLock%d\n", 54, 1, i10);
							ReleaseLock(ccBreakLock[i10]);
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager acquiring ccInterActionLock%d\n", 39, 1, i10);
							AcquireLock(ccInteractionLock[i10]);
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager releasing ccInteractionLock%d\n", 39, 1, i10);
							ReleaseLock(ccInteractionLock[i10]);
							ccState[i10] = CLERK_AVAILABLE;
							ccsOnBreak--;						
							break;
						}
					}/*
						//disband longest line*/
						if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager broadcasting ccLineCondition%d\n", 40, 1, longestLineIndex);
						BroadcastCondition(ccLineCondition[longestLineIndex], ccLineManager);
						ccLineLength[longestLineIndex] = 0;
				}
				if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager releasing tcLineManager\n", 33, 0 ,0);
				ReleaseLock(tcLineManager);
			}
			
			
			if(ttsOnBreak > 0)
			{
				if(PRINT_DEBUG_MESSAGES)
					FPrint("Manager acquiring ttLineManager\n", 33, 0, 0);
				AcquireLock(ttLineManager);
				longestLineLength = -1;
				longestLineIndex = -1;
				
				/*/find longest line of a clerk that is not on break*/
				for(i11 = 0; i11 < NUM_TICKET_TAKERS; i11++)
				{	
					if((ttState[i11] != CLERK_ON_BREAK) && (ttLineLength[i11] > longestLineLength))
					{
						longestLineLength = ttLineLength[i11];
						longestLineIndex = i11;
					}
				}
				
				if(longestLineLength > MANAGER_LONGLINE)
				{/*
					//find someone to take off break
					//take them off break
					//disband longest line*/
							
					for(i12 = 0; i12 < NUM_TICKET_TAKERS; i12++)
					{
						if(ttState[i12] == CLERK_ON_BREAK)
						{	
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager acquiring ttBreakLock%d\n", 33, 1, i12);
							AcquireLock(ttBreakLock[i12]);
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager signalling ttBreakCondition%d\n", 39, 1, i12);
							SignalCondition(ttBreakCondition[i12], ttBreakLock[i12]);
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager waiting on ttBreakCondition%d\n", 39, 1, i12);
							WaitCondition(ttBreakCondition[i12], ttBreakLock[i12]);
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager signalled awake and releasing ttBreakLock%d\n", 53, 1, i12);
							ReleaseLock(ttBreakLock[i12]);
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager acquiring ttInteractionLock%d\n", 39, 1, i12);
							AcquireLock(ttInteractionLock[i12]);
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager releasing ttInteractionLock%d\n", 39, 1, i12);
							ReleaseLock(ttInteractionLock[i12]);
							ttState[i12] = CLERK_AVAILABLE;
							ttsOnBreak--;						
							break;
						}
					}/*
						//disband longest line*/
						if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager broadcasting ttLineCondition%d\n", 40, 1, longestLineIndex);
						BroadcastCondition(ttLineCondition[longestLineIndex], ttLineManager);
						ttLineLength[longestLineIndex] = 0;
				}
				if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager releasing ttLineManager\n", 33, 0, 0);
				ReleaseLock(ttLineManager);
			}
			
			/*
			//on loop multiple of XXXX
			//process putting one person on break on break. remember to not put full ticket takers on break.
			//must disband line after putting someone on break
			*/
			
			if(loops % MANAGER_DELAY_BREAK == 0)
			{
				if(tcsOnBreak < NUM_TICKET_CLERKS - 1)
				{
					if(PRINT_DEBUG_MESSAGES)
						FPrint("Manager acquiring tcLineManager\n", 33, 0, 0);
					AcquireLock(tcLineManager);
					
					/*/check to see if anyone has no one in their line (force avail to break scenario)*/
					
					for(i13 = 0; i13 < NUM_TICKET_CLERKS; i13++)
					{
						FPrint("Manager: TicketClerk %d has state %d\n", 38, 2, i13*100 + tcState[i13]);
						if(tcState[i13] == CLERK_AVAILABLE)
						{
							if(RandInt() % 101 <= MANAGER_ROLL_ONBREAK)
							{
								tcState[i13] = CLERK_ON_BREAK;
								tcsOnBreak++;
								if(PRINT_DEBUG_MESSAGES)
									FPrint("Manager acquiring tcInteractionLock%d\n", 39, 1, i13);
								AcquireLock(tcInteractionLock[i13]);
								if(PRINT_DEBUG_MESSAGES)
									FPrint("Manager signalling tcInteractionConditon%d\n", 44, 1, i13);
								SignalCondition(tcInteractionCondition[i13], tcInteractionLock[i13]);
								if(PRINT_DEBUG_MESSAGES)
									FPrint("Manager waiting tcInteractionCondition%d\n", 42, 1, i13);
								WaitCondition(tcInteractionCondition[i13], tcInteractionLock[i13]);
								if(PRINT_DEBUG_MESSAGES)
									FPrint("Manager releasing tcInteractionLock%d\n", 39, 1, i13);
								ReleaseLock(tcInteractionLock[i13]);
								if(PRINT_DEBUG_MESSAGES)
									FPrint("Manager acquiring tcInteractionLock%d\n", 39, 1, i13);
								AcquireLock(tcBreakLock[i13]);
								if(PRINT_DEBUG_MESSAGES)
									FPrint("Manager releasing tcInteractionLock%d\n", 39, 1, i13);
								ReleaseLock(tcBreakLock[i13]);
								
								/*/disband line*/
								if(PRINT_DEBUG_MESSAGES)
									FPrint("Manager broadcasting tcLineCondition%d\n", 40, 1, i13);
								BroadcastCondition(tcLineCondition[i13], tcLineManager);
								tcLineLength[i13] = 0;
							}
							
							if(PRINT_DEBUG_MESSAGES)
								FPrint("Manager releasing tcLineManager\n", 33, 0 ,0);
							ReleaseLock(tcLineManager);
							goto managerEnd;
						}
					}
					
					/*/loop through ACTIVE line lengths and find the first person with less than MANAGER_SHORTLINE people*/
					shortLineIndex = -1;
					for(j0 = 0; j0 < NUM_TICKET_CLERKS; j0++)
					{
						if((tcState[j0] != CLERK_ON_BREAK)&&(tcLineLength[j0] < MANAGER_SHORTLINE))
						{
							shortLineIndex = j0;
							break;
						}
					}
					
					if(PRINT_DEBUG_MESSAGES)
						FPrint("Manager releasing tcLineManager\n", 33, 0, 0);
					ReleaseLock(tcLineManager);
						
					if((shortLineIndex != -1)  && (RandInt() % 101 <= MANAGER_ROLL_ONBREAK))
					{
						k0 = shortLineIndex;
						if(PRINT_DEBUG_MESSAGES)
							FPrint("Manager acquiring tcStateLock%d\n", 33, 1, k0);
						AcquireLock(tcStateLock[k0]);
						tcState[k0] = CLERK_ON_BREAK;
						tcsOnBreak++;
						if(PRINT_DEBUG_MESSAGES)
							FPrint("Manager acquiring tcBreakStopLock%d\n", 37, 1, k0);
						AcquireLock(tcBreakStopLock[k0]);
						if(PRINT_DEBUG_MESSAGES)
							FPrint("Manager releasing tcStateLock%d\n", 33, 1, k0);
						ReleaseLock(tcStateLock[k0]);
						if(PRINT_DEBUG_MESSAGES)
							FPrint("Manager waiting on tcBreakStopCondition%d\n", 43, 1, k0);
						WaitCondition(tcBreakStopCondition[k0], tcBreakStopLock[k0]);
						if(PRINT_DEBUG_MESSAGES)
							FPrint("Manager releasing tcBreakStopLock%d\n", 37, 1, k0);
						ReleaseLock(tcBreakStopLock[k0]);
						if(PRINT_DEBUG_MESSAGES)
							FPrint("Manager acquiring tcBreakLock%d\n", 33, 1, k0);
						AcquireLock(tcBreakLock[k0]);
						if(PRINT_DEBUG_MESSAGES)
							FPrint("Manager releasing tcBreakLock%d\n", 33, 1, k0);
						ReleaseLock(tcBreakLock[k0]);
						
						if(PRINT_DEBUG_MESSAGES)
							FPrint("Manager broadcasting tcLineCondtion%d\n", 39, 1, k0);
						BroadcastCondition(tcLineCondition[k0], tcLineManager);
						tcLineLength[k0] = 0;
						
						goto managerEnd;
						
					}
					
					
					if(PRINT_DEBUG_MESSAGES)
							FPrint("Manager releasing tcLineManager\n", 33, 0, 0);
						ReleaseLock(tcLineManager);
				}
			
				
				if(ccsOnBreak < NUM_CONCESSION_CLERKS - 1)
				{
				
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: acquiring ccLineManager\n", 34, 0, 0);
					AcquireLock(ccLineManager);
					
					/*/check to see if anyone has no one in their line (force avail to break scenario)*/
					
					for(i14 = 0; i14 < NUM_CONCESSION_CLERKS; i14++)
					{
						if(ccState[i14] == CLERK_AVAILABLE )
						{
							if(RandInt() % 101 <= MANAGER_ROLL_ONBREAK)
							{
								ccState[i14] = CLERK_ON_BREAK;
								ccsOnBreak++;
								if(PRINT_DEBUG_MESSAGES) FPrint("Manager: acquiring ccInteractionLock %d\n", 41, 1, i14);
								AcquireLock(ccInteractionLock[i14]);
								if(PRINT_DEBUG_MESSAGES) FPrint("Manager: signalling ccInteractionLock %d\n", 42, 1, i14);
								SignalCondition(ccInteractionCondition[i14], ccInteractionLock[i14]);
								if(PRINT_DEBUG_MESSAGES) FPrint("Manager: waiting ccInteractionLock %d\n", 39, 1, i14);
								WaitCondition(ccInteractionCondition[i14], ccInteractionLock[i14]);
								if(PRINT_DEBUG_MESSAGES) FPrint("Manager: releasing ccInteractionLock %d\n", 41, 1, i14);
								ReleaseLock(ccInteractionLock[i14]);
								if(PRINT_DEBUG_MESSAGES) FPrint("Manager: acquiring ccBreakLock %d\n", 35, 1, i14);
								AcquireLock(ccBreakLock[i14]);
								if(PRINT_DEBUG_MESSAGES) FPrint("Manager: releasing ccBreakLock %d\n", 35, 1, i14);
								ReleaseLock(ccBreakLock[i14]);
								
								/*/disband line*/
								if(PRINT_DEBUG_MESSAGES) FPrint("Manager: broadcasting ccLineCondition %d\n", 42, 1, i14);
								BroadcastCondition(ccLineCondition[i14], ccLineManager);
								ccLineLength[i14] = 0;
							}
							
							if(PRINT_DEBUG_MESSAGES) FPrint("Manager: releasing ccLineManager\n", 34, 0, 0);
							ReleaseLock(ccLineManager);
							goto managerEnd;
						}
					}
						
					/*/loop through ACTIVE line lengths and find the first person with less than MANAGER_SHORTLINE people*/
					shortLineIndex = -1;
					for(j1 = 0; j1 < NUM_CONCESSION_CLERKS; j1++)
					{
						if((ccState[j1] != CLERK_ON_BREAK)&&(ccLineLength[j1] < MANAGER_SHORTLINE))
						{
							shortLineIndex = j1;
							break;
						}
					}
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: releasing ccLineManager\n", 34, 0, 0);
					ReleaseLock(ccLineManager);
					if((shortLineIndex != -1)  && (RandInt() % 101 <= MANAGER_ROLL_ONBREAK))
					{
						k1 = shortLineIndex;
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: acquiring ccStateLock %d\n", 35, 1, k1);
						AcquireLock(ccStateLock[k1]);
						ccState[k1] = CLERK_ON_BREAK;
						ccsOnBreak++;
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: acquiring ccBreakStoplock %d\n", 39, 1, k1);
						AcquireLock(ccBreakStopLock[k1]);
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: releasing ccStateLock %d\n", 35, 1, k1);
						ReleaseLock(ccStateLock[k1]);
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: waiting ccBreakStopLock %d\n", 37, 1, k1);
						WaitCondition(ccBreakStopCondition[k1], ccBreakStopLock[k1]);
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: releasing ccBreakStopLock %d\n", 39, 1, k1);
						ReleaseLock(ccBreakStopLock[k1]);
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: acquiring ccBreakLock %d\n", 35, 1, k1);
						AcquireLock(ccBreakLock[k1]);
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: releasing ccBreakLock %d\n", 35, 1, k1);
						ReleaseLock(ccBreakLock[k1]);
						
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: broadcasting ccLineManager %d\n", 40, 1, k1);
						BroadcastCondition(ccLineCondition[k1], ccLineManager);
						ccLineLength[k1] = 0;
						
						goto managerEnd;
					}
					
					ReleaseLock(ccLineManager);
				}
				
				/*
				//full or forced to stop ticket takers cannot go on break
				//cannot put last active ticket taker on break
				//first count active ticket takers (not on break, not full and not forced to stop)
				*/
				activeTicketTakers1 = 0;
				AcquireLock(ttLineManager);
				for(i15 = 0; i15 < NUM_TICKET_TAKERS; i15++)
				{
					if(ttState[i15] == CLERK_AVAILABLE)
					{
						if(!ttForcedToStop[i15] && !ticketTakerFull[i15])
						{
						activeTicketTakers1++;
						}
					}
					else
					{
						AcquireLock(ttStateLock[i15]);
						if(ttState[i15] != CLERK_ON_BREAK && !ttForcedToStop[i15] && !ticketTakerFull[i15])
						{
						activeTicketTakers1++;
						}
					}
				}
				
				if(activeTicketTakers1 > 1)
				{
					/*/ttLineManager -> Acquire();*/
					
					/*/check to see if anyone has no one in their line (force avail to break scenario)*/
					
					for(i16 = 0; i16 < NUM_CONCESSION_CLERKS; i16++)
					{
						if(ttState[i16] == CLERK_AVAILABLE && !ticketTakerFull[i16] && !ttForcedToStop[i16])
						{
							if(RandInt() % 101 <= MANAGER_ROLL_ONBREAK)
							{
								ttState[i16] = CLERK_ON_BREAK;
								ttsOnBreak++;
								if(PRINT_DEBUG_MESSAGES) FPrint("Manager: acquiring ttInteractionLock %d\n", 41, 1, i16);
								AcquireLock(ttInteractionLock[i16]);
								if(PRINT_DEBUG_MESSAGES) FPrint("Manager: signalling ttInteractionLock %d\n", 42, 1, i16);
								SignalCondition(ttInteractionCondition[i16], ttInteractionLock[i16]);
								if(PRINT_DEBUG_MESSAGES) FPrint("Manager: waiting ttInteractionLock %d\n", 39, 1, i16);
								WaitCondition(ttInteractionCondition[i16], ttInteractionLock[i16]);
								if(PRINT_DEBUG_MESSAGES) FPrint("Manager: releasing ttInteractionLock %d\n", 41, 1, i16);
								ReleaseLock(ttInteractionLock[i16]);
								if(PRINT_DEBUG_MESSAGES) FPrint("Manager: acquiring ttBreakLock %d\n", 35, 1, i16);
								AcquireLock(ttBreakLock[i16]);
								if(PRINT_DEBUG_MESSAGES) FPrint("Manager: releasing ttBreakLock %d\n", 35, 1, i16);
								ReleaseLock(ttBreakLock[i16]);
								
								/*/disband line*/
								if(PRINT_DEBUG_MESSAGES) FPrint("Manager: broadcasting ttLineManager\n", 37, 0, 0);
								BroadcastCondition(ttLineCondition[i16], ttLineManager);
								ttLineLength[i16] = 0;
							}
							/*	
							//release stuff acquired earlier
							//ttStateLock[i] -> Release(); //never owned this lock since [i] was available*/
							for(j2 = 0; j2 < NUM_TICKET_TAKERS; j2++)
							{
								if(ttState[j2] != CLERK_AVAILABLE)
								{
									ReleaseLock(ttStateLock[j2]);
								}
							}
							
							if(PRINT_DEBUG_MESSAGES) FPrint("Manager: releasing ttLineManager\n", 34, 0, 0);
							ReleaseLock(ttLineManager);
							goto managerEnd;
						}
					}
						
					/*/loop through ACTIVE line lengths and find the first person with less than MANAGER_SHORTLINE people*/
					shortLineIndex = -1;
					for(j3 = 0; j3 < NUM_TICKET_TAKERS; j3++)
					{
						if((ttState[j3] != CLERK_ON_BREAK)&&(ttLineLength[j3] < MANAGER_SHORTLINE)&& !ticketTakerFull[j3] && !ttForcedToStop[j3])
						{
							shortLineIndex = j3;
							break;
						}
					}
						
					if(PRINT_DEBUG_MESSAGES) FPrint("Manager: releasing ttLineManager\n", 34, 0, 0);
					ReleaseLock(ttLineManager);
					
					if((shortLineIndex != -1)  && (RandInt() % 101 <= MANAGER_ROLL_ONBREAK) && !ticketTakerFull[shortLineIndex] && !ttForcedToStop[shortLineIndex])
					{
						k2 = shortLineIndex;
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: acquiring ttStateLock %d\n", 35, 1, k2);
						AcquireLock(ttStateLock[k2]);
						ttState[k2] = CLERK_ON_BREAK;
						ttsOnBreak++;
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: acquiring ttBreakStopLock %d\n", 39, 1, k2);
						AcquireLock(ttBreakStopLock[k2]);
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: releasing ttStateLock %d\n", 35, 1, k2);
						ReleaseLock(ttStateLock[k2]);
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: waiting ttBreakStopLock %d\n", 37, 1, k2);
						WaitCondition(ttBreakStopCondition[k2], ttBreakStopLock[k2]);
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: releasing ttBreakStopLock %d\n", 39, 1, k2);
						ReleaseLock(ttBreakStopLock[k2]);
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: acquiring ttBreakLock %d\n", 35, 1, k2);
						AcquireLock(ttBreakLock[k2]);
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: releasing ttBreakLock %d\n", 35, 1, k2);
						ReleaseLock(ttBreakLock[k2]);
						
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: broadcasting ttLineManager\n", 37, 0, 0);
						BroadcastCondition(ttLineCondition[k2], ttLineManager);
						ttLineLength[k2] = 0;
						
						if(PRINT_DEBUG_MESSAGES) FPrint("Manager: releasing ttStateLock %d\n", 35, 1, k2);
						ReleaseLock(ttStateLock[k2]);
						for(j4 = 0; j4 < NUM_TICKET_TAKERS; j4++)
						{
							if(ttState[j4] != CLERK_AVAILABLE)
							{
								ReleaseLock(ttStateLock[j4]);
							}
						}
						
						goto managerEnd;
					}
					ReleaseLock(ttLineManager);
				}		
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			}
		
		
		
		
		
		
		
		
		
		
		
			/*
			if(PRINT_DEBUG_MESSAGES) printf("Manager: Releasing all state locks\n");
			for(int i = 0; i < NUM_TICKET_CLERKS; i++)
			{
				tcStateLock[i] -> Release();
			}
			
			for(int i = 0; i < NUM_CONCESSION_CLERKS; i++)
			{
				ccStateLock[i] -> Release();
			}
			
			for(int i = 0; i < NUM_TICKET_TAKERS; i++)
			{
				ttStateLock[i] -> Release();
			}
			*/
		
		
	
	
		}
	
	
	
		managerEnd:
		AcquireLock(numCustomersInTheaterLock);
		if(PRINT_DEBUG_MESSAGES) FPrint("Manager: There are %d customers remaining in the theater.\n", 59, 1, numCustomersInTheater);
	}
	while(numCustomersInTheater > 0);
	ReleaseLock(numCustomersInTheaterLock);
	

	
	
	
	if(PRINT_OUTPUT_MESSAGES) FPrint("No more customers in theater. Manager exiting.\n", 48, 0, 0);
	if(PRINT_DEBUG_MESSAGES) FPrint("No more customers in theater. Manager exiting.\n", 48, 0, 0);
	
	
	
	
	Exit(0);
	/*
	//maybe destroy all the locks here?
	//might be better to have the OS kill the locks cuz when the manager dies, other threads might still own locks
	//or does it not matter, since the program is ending anyway?*/
}

/*/======== Movie Technician Function ========*/
void MovieTechnician()
{
	int myIndex;
	int ticketCount;
	int theaterCount;
	
	int i0;

	myIndex = 0;
	
	
	
	
	if(PRINT_DEBUG_MESSAGES) FPrint("MovieTechnician: created\n", 26, 0, 0);
	
	while(1){
	
		/*/Wait for Manager to acknowledge movie is sold out*/
		if(PRINT_DEBUG_MESSAGES) FPrint("MovieTechnician: acquiring movieTechLock\n", 42, 0, 0);
		AcquireLock(movieTechLock);
		if(PRINT_DEBUG_MESSAGES) FPrint("MovieTechnician: waiting for Manager to signal\n", 48, 0, 0);
		WaitCondition(movieTechCondition, movieTechLock);
		if(PRINT_DEBUG_MESSAGES) FPrint("MovieTechnician: signalled out of movieTechLock\n", 49, 0, 0);
		ReleaseLock(movieTechLock);

			
			
			if(PRINT_DEBUG_MESSAGES)
				FPrint("MovieTechnician waiting for theater to fill\n", 45, 0, 0);
				
			
				
			/*/ Wait for everyone to be seated in the theater*/
			do{		
				Yield();
				/*/Check current ticket count*/
				AcquireLock(ticketCountBoxLock);			
				ticketCount = ticketCountBox;		
				ReleaseLock(ticketCountBoxLock);
				
				/*/Check number of customers seated in the screening room*/
				AcquireLock(screeningRoomLock);
				theaterCount = getNumTakenSeats();
				ReleaseLock(screeningRoomLock);
				
				if(PRINT_DEBUG_MESSAGES)
					FPrint("MovieTechnician: ticketCount = %d, theaterCount = %d\n", 54, 2, ticketCount*100 + theaterCount);
			
			}while(ticketCount > theaterCount);

			if(PRINT_DEBUG_MESSAGES)
				FPrint("MovieTechnician changing movie status to in progress\n", 54, 0, 0);
			/*/Change the movie status to in progress*/
			AcquireLock(movieStateLock);
			MOVIE_STATE = IN_PROGRESS;
			movieNumber++;
			if(PRINT_DEBUG_MESSAGES) FPrint("MovieTechnician: Starting movie %d with %d customers in theater\n", 65, 2, movieNumber*100 + theaterCount);
			ReleaseLock(movieStateLock);
			
			AcquireLock(ticketCountBoxLock);			
			ticketCountBox = 0;		
			ReleaseLock(ticketCountBoxLock);
			
			if(PRINT_DEBUG_MESSAGES) FPrint("MovieTechnician yeilding\n", 26, 0, 0);
			if(PRINT_OUTPUT_MESSAGES) FPrint("The MovieTechnician has started the movie.\n", 44, 0, 0);
				
			for(i0 = 0;i0 < ((RandInt() % 101) + 200);i0++){
				Yield();
			}
			
			if(PRINT_DEBUG_MESSAGES) FPrint("MovieTechnician: Finished movie %d with %d customers in theater\n", 65, 2, movieNumber*100 + theaterCount);
			if(PRINT_OUTPUT_MESSAGES) FPrint("The MovieTechnician has ended the movie.\n", 42, 0, 0);
			
			/*/Change the movie status to in progress*/
			AcquireLock(movieStateLock);
			MOVIE_STATE = ROOM_EMPTYING;
			ReleaseLock(movieStateLock);
			
			if(PRINT_DEBUG_MESSAGES)
				FPrint("MovieTechnician telling customers to leave\n", 44, 0, 0);
			AcquireLock(movieInProgressLock);
			BroadcastCondition(movieInProgressCondition, movieInProgressLock);
			ReleaseLock(movieInProgressLock);
			
			if(PRINT_OUTPUT_MESSAGES) FPrint("The MovieTechnician has told all customers to leave the theater room.\n", 71, 0, 0);
			if(PRINT_DEBUG_MESSAGES) FPrint("MovieTechnician waiting for screening room to empty\n", 53, 0, 0);
			do{
				Yield();
				/*/Check number of customers seated in the screening room*/
				AcquireLock(screeningRoomLock);
				theaterCount = getNumTakenSeats();
				ReleaseLock(screeningRoomLock);
				
			}while(theaterCount > 0);
			
			/*/Change the movie status to in progress*/
			AcquireLock(movieStateLock);
			if(PRINT_DEBUG_MESSAGES) FPrint("MovieTechnician setting MOVIE_STATE to ROOM_EMPTY\n", 51, 0, 0);
			MOVIE_STATE = ROOM_EMPTY;
			ReleaseLock(movieStateLock);
		
	}
}

int main() 
{
	FPrint("==== Starting movietheater user program ====\n", 46, 0, 0);
	setupMovieTheater();
	FPrint("==== movietheater user program started ====\n", 45, 0, 0);
}













